@@ -222,15 +222,12 @@ enum LifetimeRibKind {
222222 /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
223223 AnonConst ,
224224
225- /// For **Modern** cases, create a new anonymous region parameter
226- /// and reference that.
227- ///
228- /// For **Dyn Bound** cases, pass responsibility to
229- /// `resolve_lifetime` code.
230- ///
231- /// For **Deprecated** cases, report an error.
225+ /// Create a new anonymous region parameter and reference that.
232226 AnonymousCreateParameter ( NodeId ) ,
233227
228+ /// Give a hard error when generic lifetime arguments are elided.
229+ ReportElidedInPath ,
230+
234231 /// Give a hard error when either `&` or `'_` is written. Used to
235232 /// rule out things like `where T: Foo<'_>`. Does not imply an
236233 /// error on default object bounds (e.g., `Box<dyn Foo>`).
@@ -746,8 +743,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
746743 this. with_lifetime_rib (
747744 LifetimeRibKind :: AnonymousCreateParameter ( fn_id) ,
748745 |this| {
749- // Add each argument to the rib.
750- this. resolve_params ( & declaration. inputs )
746+ this. with_lifetime_rib ( LifetimeRibKind :: ReportElidedInPath , |this| {
747+ // Add each argument to the rib.
748+ this. resolve_params ( & declaration. inputs )
749+ } ) ;
751750 } ,
752751 ) ;
753752
@@ -1301,7 +1300,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13011300 let rib = & mut self . lifetime_ribs [ i] ;
13021301 match rib. kind {
13031302 LifetimeRibKind :: AnonymousCreateParameter ( item_node_id) => {
1304- self . create_fresh_lifetime ( lifetime. id , lifetime. ident , item_node_id) ;
1303+ let region =
1304+ self . create_fresh_lifetime ( lifetime. id , lifetime. ident , item_node_id) ;
1305+ self . record_lifetime_res ( lifetime. id , region) ;
13051306 return ;
13061307 }
13071308 LifetimeRibKind :: AnonymousReportError => {
@@ -1358,7 +1359,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13581359 }
13591360
13601361 #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
1361- fn create_fresh_lifetime ( & mut self , id : NodeId , ident : Ident , item_node_id : NodeId ) {
1362+ fn create_fresh_lifetime (
1363+ & mut self ,
1364+ id : NodeId ,
1365+ ident : Ident ,
1366+ item_node_id : NodeId ,
1367+ ) -> LifetimeRes {
13621368 debug_assert_eq ! ( ident. name, kw:: UnderscoreLifetime ) ;
13631369 debug ! ( ?ident. span) ;
13641370 let item_def_id = self . r . local_def_id ( item_node_id) ;
@@ -1373,12 +1379,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13731379 debug ! ( ?def_id) ;
13741380
13751381 let region = LifetimeRes :: Fresh { param : def_id, binder : item_node_id } ;
1376- self . record_lifetime_res ( id, region) ;
13771382 self . r . extra_lifetime_params_map . entry ( item_node_id) . or_insert_with ( Vec :: new) . push ( (
13781383 ident,
13791384 def_node_id,
13801385 region,
13811386 ) ) ;
1387+ region
13821388 }
13831389
13841390 #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
@@ -1391,7 +1397,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13911397 path_span : Span ,
13921398 ) {
13931399 let proj_start = path. len ( ) - partial_res. unresolved_segments ( ) ;
1394- for ( i, segment) in path. iter ( ) . enumerate ( ) {
1400+ ' segment : for ( i, segment) in path. iter ( ) . enumerate ( ) {
13951401 if segment. has_lifetime_args {
13961402 continue ;
13971403 }
@@ -1428,16 +1434,69 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14281434 | PathSource :: Struct
14291435 | PathSource :: TupleStruct ( ..) => false ,
14301436 } ;
1431- let mut res = LifetimeRes :: Error ;
1437+
1438+ let node_ids = self . r . next_node_ids ( expected_lifetimes) ;
1439+ self . record_lifetime_res (
1440+ segment_id,
1441+ LifetimeRes :: ElidedAnchor { start : node_ids. start , end : node_ids. end } ,
1442+ ) ;
1443+
1444+ if !missing {
1445+ for i in 0 ..expected_lifetimes {
1446+ let id = node_ids. start . plus ( i) ;
1447+ self . record_lifetime_res (
1448+ id,
1449+ LifetimeRes :: Anonymous { binder : DUMMY_NODE_ID , elided : true } ,
1450+ ) ;
1451+ }
1452+ continue ;
1453+ }
1454+
1455+ let elided_lifetime_span = if segment. has_generic_args {
1456+ // If there are brackets, but not generic arguments, then use the opening bracket
1457+ segment. args_span . with_hi ( segment. args_span . lo ( ) + BytePos ( 1 ) )
1458+ } else {
1459+ // If there are no brackets, use the identifier span.
1460+ // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1461+ // originating from macros, since the segment's span might be from a macro arg.
1462+ segment. ident . span . find_ancestor_inside ( path_span) . unwrap_or ( path_span)
1463+ } ;
1464+
14321465 for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
14331466 match rib. kind {
1434- // In create-parameter mode we error here because we don't want to support
1435- // deprecated impl elision in new features like impl elision and `async fn`,
1436- // both of which work using the `CreateParameter` mode:
1437- //
1438- // impl Foo for std::cell::Ref<u32> // note lack of '_
1439- // async fn foo(_: std::cell::Ref<u32>) { ... }
1440- LifetimeRibKind :: AnonymousCreateParameter ( _) => {
1467+ // We error here because we don't want to support deprecated impl elision in
1468+ // new features like impl elision and `async fn`,
1469+ LifetimeRibKind :: ReportElidedInPath => {
1470+ let sess = self . r . session ;
1471+ let mut err = rustc_errors:: struct_span_err!(
1472+ sess,
1473+ path_span,
1474+ E0726 ,
1475+ "implicit elided lifetime not allowed here"
1476+ ) ;
1477+ rustc_errors:: add_elided_lifetime_in_path_suggestion (
1478+ sess. source_map ( ) ,
1479+ & mut err,
1480+ expected_lifetimes,
1481+ path_span,
1482+ !segment. has_generic_args ,
1483+ elided_lifetime_span,
1484+ ) ;
1485+ err. note ( "assuming a `'static` lifetime..." ) ;
1486+ err. emit ( ) ;
1487+ for i in 0 ..expected_lifetimes {
1488+ let id = node_ids. start . plus ( i) ;
1489+ self . record_lifetime_res ( id, LifetimeRes :: Error ) ;
1490+ }
1491+ continue ' segment;
1492+ }
1493+ LifetimeRibKind :: AnonymousCreateParameter ( binder) => {
1494+ let ident = Ident :: new ( kw:: UnderscoreLifetime , elided_lifetime_span) ;
1495+ for i in 0 ..expected_lifetimes {
1496+ let id = node_ids. start . plus ( i) ;
1497+ let res = self . create_fresh_lifetime ( id, ident, binder) ;
1498+ self . record_lifetime_res ( id, res) ;
1499+ }
14411500 break ;
14421501 }
14431502 // `PassThrough` is the normal case.
@@ -1447,75 +1506,40 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14471506 // lifetime. Instead, we simply create an implicit lifetime, which will be checked
14481507 // later, at which point a suitable error will be emitted.
14491508 LifetimeRibKind :: AnonymousPassThrough ( binder, _) => {
1450- res = LifetimeRes :: Anonymous { binder, elided : true } ;
1509+ let res = LifetimeRes :: Anonymous { binder, elided : true } ;
1510+ for i in 0 ..expected_lifetimes {
1511+ let id = node_ids. start . plus ( i) ;
1512+ self . record_lifetime_res ( id, res) ;
1513+ }
14511514 break ;
14521515 }
14531516 LifetimeRibKind :: AnonymousReportError | LifetimeRibKind :: Item => {
14541517 // FIXME(cjgillot) This resolution is wrong, but this does not matter
14551518 // since these cases are erroneous anyway. Lifetime resolution should
14561519 // emit a "missing lifetime specifier" diagnostic.
1457- res = LifetimeRes :: Anonymous { binder : DUMMY_NODE_ID , elided : true } ;
1520+ let res = LifetimeRes :: Anonymous { binder : DUMMY_NODE_ID , elided : true } ;
1521+ for i in 0 ..expected_lifetimes {
1522+ let id = node_ids. start . plus ( i) ;
1523+ self . record_lifetime_res ( id, res) ;
1524+ }
14581525 break ;
14591526 }
14601527 _ => { }
14611528 }
14621529 }
14631530
1464- let node_ids = self . r . next_node_ids ( expected_lifetimes ) ;
1465- self . record_lifetime_res (
1531+ self . r . lint_buffer . buffer_lint_with_diagnostic (
1532+ lint :: builtin :: ELIDED_LIFETIMES_IN_PATHS ,
14661533 segment_id,
1467- LifetimeRes :: ElidedAnchor { start : node_ids. start , end : node_ids. end } ,
1468- ) ;
1469- for i in 0 ..expected_lifetimes {
1470- let id = node_ids. start . plus ( i) ;
1471- self . record_lifetime_res ( id, res) ;
1472- }
1473-
1474- if !missing {
1475- continue ;
1476- }
1477-
1478- let elided_lifetime_span = if segment. has_generic_args {
1479- // If there are brackets, but not generic arguments, then use the opening bracket
1480- segment. args_span . with_hi ( segment. args_span . lo ( ) + BytePos ( 1 ) )
1481- } else {
1482- // If there are no brackets, use the identifier span.
1483- // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1484- // originating from macros, since the segment's span might be from a macro arg.
1485- segment. ident . span . find_ancestor_inside ( path_span) . unwrap_or ( path_span)
1486- } ;
1487- if let LifetimeRes :: Error = res {
1488- let sess = self . r . session ;
1489- let mut err = rustc_errors:: struct_span_err!(
1490- sess,
1491- path_span,
1492- E0726 ,
1493- "implicit elided lifetime not allowed here"
1494- ) ;
1495- rustc_errors:: add_elided_lifetime_in_path_suggestion (
1496- sess. source_map ( ) ,
1497- & mut err,
1534+ elided_lifetime_span,
1535+ "hidden lifetime parameters in types are deprecated" ,
1536+ lint:: BuiltinLintDiagnostics :: ElidedLifetimesInPaths (
14981537 expected_lifetimes,
14991538 path_span,
15001539 !segment. has_generic_args ,
15011540 elided_lifetime_span,
1502- ) ;
1503- err. note ( "assuming a `'static` lifetime..." ) ;
1504- err. emit ( ) ;
1505- } else {
1506- self . r . lint_buffer . buffer_lint_with_diagnostic (
1507- lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS ,
1508- segment_id,
1509- elided_lifetime_span,
1510- "hidden lifetime parameters in types are deprecated" ,
1511- lint:: BuiltinLintDiagnostics :: ElidedLifetimesInPaths (
1512- expected_lifetimes,
1513- path_span,
1514- !segment. has_generic_args ,
1515- elided_lifetime_span,
1516- ) ,
1517- ) ;
1518- }
1541+ ) ,
1542+ ) ;
15191543 }
15201544 }
15211545
@@ -2072,12 +2096,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
20722096 let mut new_id = None ;
20732097 if let Some ( trait_ref) = opt_trait_ref {
20742098 let path: Vec < _ > = Segment :: from_path ( & trait_ref. path ) ;
2075- let res = self . smart_resolve_path_fragment (
2076- None ,
2077- & path,
2078- PathSource :: Trait ( AliasPossibility :: No ) ,
2079- Finalize :: new ( trait_ref. ref_id , trait_ref. path . span ) ,
2080- ) ;
2099+ let res = self . with_lifetime_rib ( LifetimeRibKind :: ReportElidedInPath , |this| {
2100+ this. smart_resolve_path_fragment (
2101+ None ,
2102+ & path,
2103+ PathSource :: Trait ( AliasPossibility :: No ) ,
2104+ Finalize :: new ( trait_ref. ref_id , trait_ref. path . span ) ,
2105+ )
2106+ } ) ;
20812107 if let Some ( def_id) = res. base_res ( ) . opt_def_id ( ) {
20822108 new_id = Some ( def_id) ;
20832109 new_val = Some ( ( self . r . expect_module ( def_id) , trait_ref. clone ( ) ) ) ;
@@ -2130,14 +2156,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21302156 let res =
21312157 Res :: SelfTy { trait_ : trait_id, alias_to : Some ( ( item_def_id, false ) ) } ;
21322158 this. with_self_rib ( res, |this| {
2133- if let Some ( trait_ref) = opt_trait_reference. as_ref ( ) {
2134- // Resolve type arguments in the trait path.
2135- visit:: walk_trait_ref ( this, trait_ref) ;
2136- }
2137- // Resolve the self type.
2138- this. visit_ty ( self_type) ;
2139- // Resolve the generic parameters.
2140- this. visit_generics ( generics) ;
2159+ this. with_lifetime_rib ( LifetimeRibKind :: ReportElidedInPath , |this| {
2160+ if let Some ( trait_ref) = opt_trait_reference. as_ref ( ) {
2161+ // Resolve type arguments in the trait path.
2162+ visit:: walk_trait_ref ( this, trait_ref) ;
2163+ }
2164+ // Resolve the self type.
2165+ this. visit_ty ( self_type) ;
2166+ // Resolve the generic parameters.
2167+ this. visit_generics ( generics) ;
2168+ } ) ;
21412169
21422170 // Resolve the items within the impl.
21432171 this. with_lifetime_rib ( LifetimeRibKind :: AnonymousPassThrough ( item_id, false ) ,
0 commit comments