@@ -2988,6 +2988,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
29882988 } else if let TyKind :: CVarArgs = param. ty . kind {
29892989 // Don't suggest `&...` for ffi fn with varargs
29902990 None
2991+ } else if let TyKind :: ImplTrait ( ..) = & param. ty . kind {
2992+ // We handle these in the next `else if` branch.
2993+ None
29912994 } else {
29922995 Some ( ( param. ty . span . shrink_to_lo ( ) , "&" . to_string ( ) ) )
29932996 }
@@ -3010,6 +3013,64 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
30103013 Applicability :: MaybeIncorrect ,
30113014 ) ;
30123015 "...or alternatively,"
3016+ } else if let Some ( ( kind, _span) ) =
3017+ self . diagnostic_metadata . current_function
3018+ && let FnKind :: Fn ( _, _, sig, _, _, _) = kind
3019+ && let ast:: FnRetTy :: Ty ( ret_ty) = & sig. decl . output
3020+ && !sig. decl . inputs . is_empty ( )
3021+ && let arg_refs = sig
3022+ . decl
3023+ . inputs
3024+ . iter ( )
3025+ . filter_map ( |param| match & param. ty . kind {
3026+ TyKind :: ImplTrait ( _, bounds) => Some ( bounds) ,
3027+ _ => None ,
3028+ } )
3029+ . flat_map ( |bounds| bounds. into_iter ( ) )
3030+ . collect :: < Vec < _ > > ( )
3031+ && !arg_refs. is_empty ( )
3032+ {
3033+ // We have a situation like
3034+ // fn g(mut x: impl Iterator<Item = &()>) -> Option<&()>
3035+ // So we look at every ref in the trait bound. If there's any, we
3036+ // suggest
3037+ // fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()>
3038+ let mut lt_finder = LifetimeFinder {
3039+ lifetime : lt. span ,
3040+ found : None ,
3041+ seen : vec ! [ ] ,
3042+ } ;
3043+ for bound in arg_refs {
3044+ if let ast:: GenericBound :: Trait ( trait_ref, _) = bound {
3045+ lt_finder. visit_trait_ref ( & trait_ref. trait_ref ) ;
3046+ }
3047+ }
3048+ lt_finder. visit_ty ( ret_ty) ;
3049+ let spans_suggs: Vec < _ > = lt_finder. seen . iter ( ) . filter_map ( |ty| {
3050+ match & ty. kind {
3051+ TyKind :: Ref ( _, mut_ty) => {
3052+ let span = ty. span . with_hi ( mut_ty. ty . span . lo ( ) ) ;
3053+ Some ( ( span, "&'a " . to_string ( ) ) )
3054+ }
3055+ _ => None
3056+ }
3057+ } ) . collect ( ) ;
3058+ self . suggest_introducing_lifetime (
3059+ err,
3060+ None ,
3061+ |err, higher_ranked, span, message, intro_sugg| {
3062+ info ! ( ?span, ?message, ?intro_sugg) ;
3063+ err. multipart_suggestion_verbose (
3064+ message,
3065+ std:: iter:: once ( ( span, intro_sugg) )
3066+ . chain ( spans_suggs. iter ( ) . cloned ( ) )
3067+ . collect ( ) ,
3068+ Applicability :: MaybeIncorrect ,
3069+ ) ;
3070+ higher_ranked
3071+ } ,
3072+ ) ;
3073+ "...or alternatively,"
30133074 } else {
30143075 "instead, you are more likely"
30153076 } ;
@@ -3019,7 +3080,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
30193080 && let FnKind :: Fn ( _, _, sig, _, _, _) = kind
30203081 && let ast:: FnRetTy :: Ty ( ty) = & sig. decl . output
30213082 {
3022- let mut lt_finder = LifetimeFinder { lifetime : lt. span , found : None } ;
3083+ let mut lt_finder = LifetimeFinder {
3084+ lifetime : lt. span ,
3085+ found : None ,
3086+ seen : vec ! [ ] ,
3087+ } ;
30233088 lt_finder. visit_ty ( & ty) ;
30243089
30253090 if let Some ( ty) = lt_finder. found {
@@ -3155,14 +3220,16 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I
31553220struct LifetimeFinder < ' ast > {
31563221 lifetime : Span ,
31573222 found : Option < & ' ast Ty > ,
3223+ seen : Vec < & ' ast Ty > ,
31583224}
31593225
31603226impl < ' ast > Visitor < ' ast > for LifetimeFinder < ' ast > {
31613227 fn visit_ty ( & mut self , t : & ' ast Ty ) {
3162- if t. span . lo ( ) == self . lifetime . lo ( )
3163- && let TyKind :: Ref ( _, mut_ty) = & t. kind
3164- {
3165- self . found = Some ( & mut_ty. ty ) ;
3228+ if let TyKind :: Ref ( _, mut_ty) = & t. kind {
3229+ self . seen . push ( t) ;
3230+ if t. span . lo ( ) == self . lifetime . lo ( ) {
3231+ self . found = Some ( & mut_ty. ty ) ;
3232+ }
31663233 }
31673234 walk_ty ( self , t)
31683235 }
0 commit comments