@@ -13,7 +13,8 @@ use std::mem::{replace, swap, take};
1313use std:: ops:: { ControlFlow , Range } ;
1414
1515use rustc_ast:: visit:: {
16- AssocCtxt , BoundKind , FnCtxt , FnKind , Visitor , try_visit, visit_opt, walk_list,
16+ AssocCtxt , BoundKind , FnCtxt , FnKind , LifetimeCtxt , Visitor , try_visit, visit_opt, walk_list,
17+ walk_ty,
1718} ;
1819use rustc_ast:: * ;
1920use rustc_data_structures:: either:: Either ;
@@ -2448,9 +2449,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
24482449 binder : fn_id,
24492450 report_in_path : report_elided_lifetimes_in_path,
24502451 } ;
2452+ let output_has_lifetime = fn_output_has_lifetime ( output_ty) ;
24512453 self . with_lifetime_rib ( rib, |this| {
24522454 // Add each argument to the rib.
2453- let elision_lifetime = this. resolve_fn_params ( has_self, inputs) ;
2455+ let elision_lifetime = this. resolve_fn_params ( has_self, inputs, output_has_lifetime ) ;
24542456 debug ! ( ?elision_lifetime) ;
24552457
24562458 let outer_failures = take ( & mut this. diag_metadata . current_elision_failures ) ;
@@ -2493,6 +2495,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
24932495 & mut self ,
24942496 has_self : bool ,
24952497 inputs : impl Iterator < Item = ( Option < & ' ast Pat > , & ' ast Ty ) > + Clone ,
2498+ output_has_lifetime : bool ,
24962499 ) -> Result < LifetimeRes , ( Vec < MissingLifetime > , Vec < ElisionFnParameter > ) > {
24972500 enum Elision {
24982501 /// We have not found any candidate.
@@ -2582,6 +2585,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
25822585 // Handle `self` specially.
25832586 if index == 0 && has_self {
25842587 let self_lifetime = self . find_lifetime_for_self ( ty) ;
2588+
2589+ if output_has_lifetime
2590+ && self . self_type_has_reference ( ty)
2591+ && !self . self_param_has_genuine_self ( ty)
2592+ {
2593+ self . r . lint_buffer . buffer_lint (
2594+ lint:: builtin:: SELF_LIFETIME_ELISION_NOT_APPLICABLE ,
2595+ ty. id ,
2596+ ty. span ,
2597+ crate :: errors:: SelfLifetimeElisionNotApplicable { span : ty. span } ,
2598+ ) ;
2599+ }
2600+
25852601 elision_lifetime = match self_lifetime {
25862602 // We found `self` elision.
25872603 Set1 :: One ( lifetime) => Elision :: Self_ ( lifetime) ,
@@ -2610,6 +2626,58 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
26102626 Err ( ( all_candidates, parameter_info) )
26112627 }
26122628
2629+ /// Returns `true` if `ty` syntactically contains `Self`.
2630+ fn self_param_has_genuine_self ( & self , ty : & ' ast Ty ) -> bool {
2631+ struct GenuineSelfVisitor < ' a , ' ra , ' tcx > {
2632+ r : & ' a Resolver < ' ra , ' tcx > ,
2633+ found : bool ,
2634+ }
2635+ impl < ' ra > Visitor < ' ra > for GenuineSelfVisitor < ' _ , ' _ , ' _ > {
2636+ fn visit_ty ( & mut self , ty : & ' ra Ty ) {
2637+ match ty. kind {
2638+ TyKind :: ImplicitSelf => self . found = true ,
2639+ TyKind :: Path ( None , _) => {
2640+ if matches ! (
2641+ self . r. partial_res_map[ & ty. id] . full_res( ) ,
2642+ Some ( Res :: SelfTyParam { .. } | Res :: SelfTyAlias { .. } )
2643+ ) {
2644+ self . found = true ;
2645+ }
2646+ }
2647+ _ => { }
2648+ }
2649+ if !self . found {
2650+ visit:: walk_ty ( self , ty) ;
2651+ }
2652+ }
2653+ fn visit_expr ( & mut self , _: & ' ra Expr ) { }
2654+ }
2655+ let mut visitor = GenuineSelfVisitor { r : self . r , found : false } ;
2656+ visitor. visit_ty ( ty) ;
2657+ visitor. found
2658+ }
2659+
2660+ /// Returns `true` if `ty` contains a reference type (`&` or pinned `&`).
2661+ fn self_type_has_reference ( & self , ty : & ' ast Ty ) -> bool {
2662+ struct RefVisitor {
2663+ found : bool ,
2664+ }
2665+ impl < ' ra > Visitor < ' ra > for RefVisitor {
2666+ fn visit_ty ( & mut self , ty : & ' ra Ty ) {
2667+ if matches ! ( ty. kind, TyKind :: Ref ( ..) | TyKind :: PinnedRef ( ..) ) {
2668+ self . found = true ;
2669+ }
2670+ if !self . found {
2671+ visit:: walk_ty ( self , ty) ;
2672+ }
2673+ }
2674+ fn visit_expr ( & mut self , _: & ' ra Expr ) { }
2675+ }
2676+ let mut visitor = RefVisitor { found : false } ;
2677+ visitor. visit_ty ( ty) ;
2678+ visitor. found
2679+ }
2680+
26132681 /// List all the lifetimes that appear in the provided type.
26142682 fn find_lifetime_for_self ( & self , ty : & ' ast Ty ) -> Set1 < LifetimeRes > {
26152683 /// Visits a type to find all the &references, and determines the
@@ -5593,6 +5661,30 @@ impl ItemInfoCollector<'_, '_, '_> {
55935661 }
55945662}
55955663
5664+ fn fn_output_has_lifetime ( output_ty : & FnRetTy ) -> bool {
5665+ struct Probe ( bool ) ;
5666+ impl < ' ast > Visitor < ' ast > for Probe {
5667+ fn visit_lifetime ( & mut self , _: & ' ast Lifetime , _: LifetimeCtxt ) {
5668+ self . 0 = true ;
5669+ }
5670+ fn visit_ty ( & mut self , ty : & ' ast Ty ) {
5671+ if self . 0 {
5672+ return ;
5673+ }
5674+ match & ty. kind {
5675+ TyKind :: Ref ( ..) | TyKind :: PinnedRef ( ..) | TyKind :: TraitObject ( ..) => {
5676+ self . 0 = true ;
5677+ }
5678+ _ => walk_ty ( self , ty) ,
5679+ }
5680+ }
5681+ }
5682+ let FnRetTy :: Ty ( ty) = output_ty else { return false } ;
5683+ let mut p = Probe ( false ) ;
5684+ p. visit_ty ( ty) ;
5685+ p. 0
5686+ }
5687+
55965688fn required_generic_args_suggestion ( generics : & ast:: Generics ) -> Option < String > {
55975689 let required = generics
55985690 . params
0 commit comments