@@ -238,14 +238,14 @@ enum LifetimeRibKind {
238238 /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
239239 AnonConst ,
240240
241- /// For **Modern** cases, create a new anonymous region parameter
242- /// and reference that.
241+ /// Create a new anonymous region parameter and reference it.
243242 ///
244- /// For **Dyn Bound** cases, pass responsibility to
245- /// `resolve_lifetime` code.
246- ///
247- /// For **Deprecated** cases, report an error.
248- AnonymousCreateParameter ( NodeId ) ,
243+ /// If `report_in_path`, report an error when encountering lifetime elision in a path:
244+ /// ```ignore
245+ /// struct Foo<'a> { .. }
246+ /// fn foo(x: Foo) {}
247+ /// ```
248+ AnonymousCreateParameter { binder : NodeId , report_in_path : bool } ,
249249
250250 /// Give a hard error when either `&` or `'_` is written. Used to
251251 /// rule out things like `where T: Foo<'_>`. Does not imply an
@@ -764,7 +764,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
764764 // return type.
765765 this. with_lifetime_rib (
766766 if async_node_id. is_some ( ) {
767- LifetimeRibKind :: AnonymousCreateParameter ( fn_id)
767+ LifetimeRibKind :: AnonymousCreateParameter {
768+ binder : fn_id,
769+ report_in_path : true ,
770+ }
768771 } else {
769772 LifetimeRibKind :: AnonymousPassThrough ( fn_id, false )
770773 } ,
@@ -791,7 +794,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
791794 ) ;
792795 match rib. kind {
793796 LifetimeRibKind :: Item => break ,
794- LifetimeRibKind :: AnonymousCreateParameter ( binder) => {
797+ LifetimeRibKind :: AnonymousCreateParameter {
798+ binder, ..
799+ } => {
795800 if let Some ( earlier_fresh) =
796801 this. r . extra_lifetime_params_map . get ( & binder)
797802 {
@@ -1295,7 +1300,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
12951300 }
12961301 // An anonymous lifetime is legal here, go ahead.
12971302 LifetimeRibKind :: AnonymousPassThrough ( _, false )
1298- | LifetimeRibKind :: AnonymousCreateParameter ( _ ) => {
1303+ | LifetimeRibKind :: AnonymousCreateParameter { .. } => {
12991304 Some ( LifetimeUseSet :: One { use_span : ident. span , use_ctxt } )
13001305 }
13011306 _ => None ,
@@ -1350,8 +1355,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13501355 for i in ( 0 ..self . lifetime_ribs . len ( ) ) . rev ( ) {
13511356 let rib = & mut self . lifetime_ribs [ i] ;
13521357 match rib. kind {
1353- LifetimeRibKind :: AnonymousCreateParameter ( item_node_id) => {
1354- self . create_fresh_lifetime ( lifetime. id , lifetime. ident , item_node_id) ;
1358+ LifetimeRibKind :: AnonymousCreateParameter { binder, .. } => {
1359+ let res = self . create_fresh_lifetime ( lifetime. id , lifetime. ident , binder) ;
1360+ self . record_lifetime_res ( lifetime. id , res) ;
13551361 return ;
13561362 }
13571363 LifetimeRibKind :: AnonymousReportError => {
@@ -1408,7 +1414,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14081414 }
14091415
14101416 #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
1411- fn create_fresh_lifetime ( & mut self , id : NodeId , ident : Ident , item_node_id : NodeId ) {
1417+ fn create_fresh_lifetime (
1418+ & mut self ,
1419+ id : NodeId ,
1420+ ident : Ident ,
1421+ item_node_id : NodeId ,
1422+ ) -> LifetimeRes {
14121423 debug_assert_eq ! ( ident. name, kw:: UnderscoreLifetime ) ;
14131424 debug ! ( ?ident. span) ;
14141425 let item_def_id = self . r . local_def_id ( item_node_id) ;
@@ -1423,12 +1434,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14231434 debug ! ( ?def_id) ;
14241435
14251436 let region = LifetimeRes :: Fresh { param : def_id, binder : item_node_id } ;
1426- self . record_lifetime_res ( id, region) ;
14271437 self . r . extra_lifetime_params_map . entry ( item_node_id) . or_insert_with ( Vec :: new) . push ( (
14281438 ident,
14291439 def_node_id,
14301440 region,
14311441 ) ) ;
1442+ region
14321443 }
14331444
14341445 #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
@@ -1471,14 +1482,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14711482 continue ;
14721483 }
14731484
1474- let missing = match source {
1485+ let mut should_lint = match source {
14751486 PathSource :: Trait ( ..) | PathSource :: TraitItem ( ..) | PathSource :: Type => true ,
14761487 PathSource :: Expr ( ..)
14771488 | PathSource :: Pat
14781489 | PathSource :: Struct
14791490 | PathSource :: TupleStruct ( ..) => false ,
14801491 } ;
1481- let mut res = LifetimeRes :: Error ;
1492+
1493+ let elided_lifetime_span = if segment. has_generic_args {
1494+ // If there are brackets, but not generic arguments, then use the opening bracket
1495+ segment. args_span . with_hi ( segment. args_span . lo ( ) + BytePos ( 1 ) )
1496+ } else {
1497+ // If there are no brackets, use the identifier span.
1498+ // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1499+ // originating from macros, since the segment's span might be from a macro arg.
1500+ segment. ident . span . find_ancestor_inside ( path_span) . unwrap_or ( path_span)
1501+ } ;
1502+ let ident = Ident :: new ( kw:: UnderscoreLifetime , elided_lifetime_span) ;
1503+
1504+ let node_ids = self . r . next_node_ids ( expected_lifetimes) ;
1505+ self . record_lifetime_res (
1506+ segment_id,
1507+ LifetimeRes :: ElidedAnchor { start : node_ids. start , end : node_ids. end } ,
1508+ ) ;
1509+
14821510 for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
14831511 match rib. kind {
14841512 // In create-parameter mode we error here because we don't want to support
@@ -1487,7 +1515,39 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14871515 //
14881516 // impl Foo for std::cell::Ref<u32> // note lack of '_
14891517 // async fn foo(_: std::cell::Ref<u32>) { ... }
1490- LifetimeRibKind :: AnonymousCreateParameter ( _) => {
1518+ LifetimeRibKind :: AnonymousCreateParameter { report_in_path : true , .. } => {
1519+ let sess = self . r . session ;
1520+ let mut err = rustc_errors:: struct_span_err!(
1521+ sess,
1522+ path_span,
1523+ E0726 ,
1524+ "implicit elided lifetime not allowed here"
1525+ ) ;
1526+ rustc_errors:: add_elided_lifetime_in_path_suggestion (
1527+ sess. source_map ( ) ,
1528+ & mut err,
1529+ expected_lifetimes,
1530+ path_span,
1531+ !segment. has_generic_args ,
1532+ elided_lifetime_span,
1533+ ) ;
1534+ err. note ( "assuming a `'static` lifetime..." ) ;
1535+ err. emit ( ) ;
1536+ should_lint = false ;
1537+ for i in 0 ..expected_lifetimes {
1538+ let id = node_ids. start . plus ( i) ;
1539+ self . record_lifetime_res ( id, LifetimeRes :: Error ) ;
1540+ }
1541+ break ;
1542+ }
1543+ LifetimeRibKind :: AnonymousCreateParameter { binder, .. } => {
1544+ let res = self . create_fresh_lifetime ( node_ids. start , ident, binder) ;
1545+ self . record_lifetime_res ( node_ids. start , res) ;
1546+ for i in 1 ..expected_lifetimes {
1547+ let id = node_ids. start . plus ( i) ;
1548+ let res = self . create_fresh_lifetime ( id, ident, binder) ;
1549+ self . record_lifetime_res ( id, res) ;
1550+ }
14911551 break ;
14921552 }
14931553 // `PassThrough` is the normal case.
@@ -1497,62 +1557,30 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14971557 // lifetime. Instead, we simply create an implicit lifetime, which will be checked
14981558 // later, at which point a suitable error will be emitted.
14991559 LifetimeRibKind :: AnonymousPassThrough ( binder, _) => {
1500- res = LifetimeRes :: Anonymous { binder, elided : true } ;
1560+ let res = LifetimeRes :: Anonymous { binder, elided : true } ;
1561+ self . record_lifetime_res ( node_ids. start , res) ;
1562+ for i in 1 ..expected_lifetimes {
1563+ let id = node_ids. start . plus ( i) ;
1564+ self . record_lifetime_res ( id, res) ;
1565+ }
15011566 break ;
15021567 }
15031568 LifetimeRibKind :: AnonymousReportError | LifetimeRibKind :: Item => {
15041569 // FIXME(cjgillot) This resolution is wrong, but this does not matter
15051570 // since these cases are erroneous anyway. Lifetime resolution should
15061571 // emit a "missing lifetime specifier" diagnostic.
1507- res = LifetimeRes :: Anonymous { binder : DUMMY_NODE_ID , elided : true } ;
1572+ let res = LifetimeRes :: Anonymous { binder : DUMMY_NODE_ID , elided : true } ;
1573+ for i in 0 ..expected_lifetimes {
1574+ let id = node_ids. start . plus ( i) ;
1575+ self . record_lifetime_res ( id, res) ;
1576+ }
15081577 break ;
15091578 }
15101579 _ => { }
15111580 }
15121581 }
15131582
1514- let node_ids = self . r . next_node_ids ( expected_lifetimes) ;
1515- self . record_lifetime_res (
1516- segment_id,
1517- LifetimeRes :: ElidedAnchor { start : node_ids. start , end : node_ids. end } ,
1518- ) ;
1519- for i in 0 ..expected_lifetimes {
1520- let id = node_ids. start . plus ( i) ;
1521- self . record_lifetime_res ( id, res) ;
1522- }
1523-
1524- if !missing {
1525- continue ;
1526- }
1527-
1528- let elided_lifetime_span = if segment. has_generic_args {
1529- // If there are brackets, but not generic arguments, then use the opening bracket
1530- segment. args_span . with_hi ( segment. args_span . lo ( ) + BytePos ( 1 ) )
1531- } else {
1532- // If there are no brackets, use the identifier span.
1533- // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1534- // originating from macros, since the segment's span might be from a macro arg.
1535- segment. ident . span . find_ancestor_inside ( path_span) . unwrap_or ( path_span)
1536- } ;
1537- if let LifetimeRes :: Error = res {
1538- let sess = self . r . session ;
1539- let mut err = rustc_errors:: struct_span_err!(
1540- sess,
1541- path_span,
1542- E0726 ,
1543- "implicit elided lifetime not allowed here"
1544- ) ;
1545- rustc_errors:: add_elided_lifetime_in_path_suggestion (
1546- sess. source_map ( ) ,
1547- & mut err,
1548- expected_lifetimes,
1549- path_span,
1550- !segment. has_generic_args ,
1551- elided_lifetime_span,
1552- ) ;
1553- err. note ( "assuming a `'static` lifetime..." ) ;
1554- err. emit ( ) ;
1555- } else {
1583+ if should_lint {
15561584 self . r . lint_buffer . buffer_lint_with_diagnostic (
15571585 lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS ,
15581586 segment_id,
@@ -2155,7 +2183,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21552183 // Dummy self type for better errors if `Self` is used in the trait path.
21562184 this. with_self_rib ( Res :: SelfTy { trait_ : None , alias_to : None } , |this| {
21572185 this. with_lifetime_rib (
2158- LifetimeRibKind :: AnonymousCreateParameter ( item_id) ,
2186+ LifetimeRibKind :: AnonymousCreateParameter {
2187+ binder : item_id,
2188+ report_in_path : true
2189+ } ,
21592190 |this| {
21602191 // Resolve the trait reference, if necessary.
21612192 this. with_optional_trait_ref (
0 commit comments