@@ -2789,6 +2789,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
27892789 } else if let TyKind :: CVarArgs = param. ty . kind {
27902790 // Don't suggest `&...` for ffi fn with varargs
27912791 None
2792+ } else if let TyKind :: ImplTrait ( ..) = & param. ty . kind {
2793+ // We handle these in the next `else if` branch.
2794+ None
27922795 } else {
27932796 Some ( ( param. ty . span . shrink_to_lo ( ) , "&" . to_string ( ) ) )
27942797 }
@@ -2811,6 +2814,64 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
28112814 Applicability :: MaybeIncorrect ,
28122815 ) ;
28132816 "...or alternatively,"
2817+ } else if let Some ( ( kind, _span) ) =
2818+ self . diagnostic_metadata . current_function
2819+ && let FnKind :: Fn ( _, _, sig, _, _, _) = kind
2820+ && let ast:: FnRetTy :: Ty ( ret_ty) = & sig. decl . output
2821+ && !sig. decl . inputs . is_empty ( )
2822+ && let arg_refs = sig
2823+ . decl
2824+ . inputs
2825+ . iter ( )
2826+ . filter_map ( |param| match & param. ty . kind {
2827+ TyKind :: ImplTrait ( _, bounds) => Some ( bounds) ,
2828+ _ => None ,
2829+ } )
2830+ . flat_map ( |bounds| bounds. into_iter ( ) )
2831+ . collect :: < Vec < _ > > ( )
2832+ && !arg_refs. is_empty ( )
2833+ {
2834+ // We have a situation like
2835+ // fn g(mut x: impl Iterator<Item = &()>) -> Option<&()>
2836+ // So we look at every ref in the trait bound. If there's any, we
2837+ // suggest
2838+ // fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()>
2839+ let mut lt_finder = LifetimeFinder {
2840+ lifetime : lt. span ,
2841+ found : None ,
2842+ seen : vec ! [ ] ,
2843+ } ;
2844+ for bound in arg_refs {
2845+ if let ast:: GenericBound :: Trait ( trait_ref, _) = bound {
2846+ lt_finder. visit_trait_ref ( & trait_ref. trait_ref ) ;
2847+ }
2848+ }
2849+ lt_finder. visit_ty ( ret_ty) ;
2850+ let spans_suggs: Vec < _ > = lt_finder. seen . iter ( ) . filter_map ( |ty| {
2851+ match & ty. kind {
2852+ TyKind :: Ref ( _, mut_ty) => {
2853+ let span = ty. span . with_hi ( mut_ty. ty . span . lo ( ) ) ;
2854+ Some ( ( span, "&'a " . to_string ( ) ) )
2855+ }
2856+ _ => None
2857+ }
2858+ } ) . collect ( ) ;
2859+ self . suggest_introducing_lifetime (
2860+ err,
2861+ None ,
2862+ |err, higher_ranked, span, message, intro_sugg| {
2863+ info ! ( ?span, ?message, ?intro_sugg) ;
2864+ err. multipart_suggestion_verbose (
2865+ message,
2866+ std:: iter:: once ( ( span, intro_sugg) )
2867+ . chain ( spans_suggs. iter ( ) . cloned ( ) )
2868+ . collect ( ) ,
2869+ Applicability :: MaybeIncorrect ,
2870+ ) ;
2871+ higher_ranked
2872+ } ,
2873+ ) ;
2874+ "...or alternatively,"
28142875 } else {
28152876 "instead, you are more likely"
28162877 } ;
@@ -2820,7 +2881,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
28202881 && let FnKind :: Fn ( _, _, sig, _, _, _) = kind
28212882 && let ast:: FnRetTy :: Ty ( ty) = & sig. decl . output
28222883 {
2823- let mut lt_finder = LifetimeFinder { lifetime : lt. span , found : None } ;
2884+ let mut lt_finder = LifetimeFinder {
2885+ lifetime : lt. span ,
2886+ found : None ,
2887+ seen : vec ! [ ] ,
2888+ } ;
28242889 lt_finder. visit_ty ( & ty) ;
28252890
28262891 if let Some ( ty) = lt_finder. found {
@@ -2956,14 +3021,16 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I
29563021struct LifetimeFinder < ' ast > {
29573022 lifetime : Span ,
29583023 found : Option < & ' ast Ty > ,
3024+ seen : Vec < & ' ast Ty > ,
29593025}
29603026
29613027impl < ' ast > Visitor < ' ast > for LifetimeFinder < ' ast > {
29623028 fn visit_ty ( & mut self , t : & ' ast Ty ) {
2963- if t. span . lo ( ) == self . lifetime . lo ( )
2964- && let TyKind :: Ref ( _, mut_ty) = & t. kind
2965- {
2966- self . found = Some ( & mut_ty. ty ) ;
3029+ if let TyKind :: Ref ( _, mut_ty) = & t. kind {
3030+ self . seen . push ( t) ;
3031+ if t. span . lo ( ) == self . lifetime . lo ( ) {
3032+ self . found = Some ( & mut_ty. ty ) ;
3033+ }
29673034 }
29683035 walk_ty ( self , t)
29693036 }
0 commit comments