@@ -238,14 +238,14 @@ enum LifetimeRibKind {
238
238
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
239
239
AnonConst ,
240
240
241
- /// For **Modern** cases, create a new anonymous region parameter
242
- /// and reference that.
241
+ /// Create a new anonymous region parameter and reference it.
243
242
///
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 } ,
249
249
250
250
/// Give a hard error when either `&` or `'_` is written. Used to
251
251
/// 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> {
764
764
// return type.
765
765
this. with_lifetime_rib (
766
766
if async_node_id. is_some ( ) {
767
- LifetimeRibKind :: AnonymousCreateParameter ( fn_id)
767
+ LifetimeRibKind :: AnonymousCreateParameter {
768
+ binder : fn_id,
769
+ report_in_path : true ,
770
+ }
768
771
} else {
769
772
LifetimeRibKind :: AnonymousPassThrough ( fn_id, false )
770
773
} ,
@@ -791,7 +794,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
791
794
) ;
792
795
match rib. kind {
793
796
LifetimeRibKind :: Item => break ,
794
- LifetimeRibKind :: AnonymousCreateParameter ( binder) => {
797
+ LifetimeRibKind :: AnonymousCreateParameter {
798
+ binder, ..
799
+ } => {
795
800
if let Some ( earlier_fresh) =
796
801
this. r . extra_lifetime_params_map . get ( & binder)
797
802
{
@@ -1295,7 +1300,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1295
1300
}
1296
1301
// An anonymous lifetime is legal here, go ahead.
1297
1302
LifetimeRibKind :: AnonymousPassThrough ( _, false )
1298
- | LifetimeRibKind :: AnonymousCreateParameter ( _ ) => {
1303
+ | LifetimeRibKind :: AnonymousCreateParameter { .. } => {
1299
1304
Some ( LifetimeUseSet :: One { use_span : ident. span , use_ctxt } )
1300
1305
}
1301
1306
_ => None ,
@@ -1350,8 +1355,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1350
1355
for i in ( 0 ..self . lifetime_ribs . len ( ) ) . rev ( ) {
1351
1356
let rib = & mut self . lifetime_ribs [ i] ;
1352
1357
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) ;
1355
1361
return ;
1356
1362
}
1357
1363
LifetimeRibKind :: AnonymousReportError => {
@@ -1408,7 +1414,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1408
1414
}
1409
1415
1410
1416
#[ 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 {
1412
1423
debug_assert_eq ! ( ident. name, kw:: UnderscoreLifetime ) ;
1413
1424
debug ! ( ?ident. span) ;
1414
1425
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> {
1423
1434
debug ! ( ?def_id) ;
1424
1435
1425
1436
let region = LifetimeRes :: Fresh { param : def_id, binder : item_node_id } ;
1426
- self . record_lifetime_res ( id, region) ;
1427
1437
self . r . extra_lifetime_params_map . entry ( item_node_id) . or_insert_with ( Vec :: new) . push ( (
1428
1438
ident,
1429
1439
def_node_id,
1430
1440
region,
1431
1441
) ) ;
1442
+ region
1432
1443
}
1433
1444
1434
1445
#[ tracing:: instrument( level = "debug" , skip( self ) ) ]
@@ -1471,14 +1482,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1471
1482
continue ;
1472
1483
}
1473
1484
1474
- let missing = match source {
1485
+ let mut should_lint = match source {
1475
1486
PathSource :: Trait ( ..) | PathSource :: TraitItem ( ..) | PathSource :: Type => true ,
1476
1487
PathSource :: Expr ( ..)
1477
1488
| PathSource :: Pat
1478
1489
| PathSource :: Struct
1479
1490
| PathSource :: TupleStruct ( ..) => false ,
1480
1491
} ;
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
+
1482
1510
for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
1483
1511
match rib. kind {
1484
1512
// 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> {
1487
1515
//
1488
1516
// impl Foo for std::cell::Ref<u32> // note lack of '_
1489
1517
// 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
+ }
1491
1551
break ;
1492
1552
}
1493
1553
// `PassThrough` is the normal case.
@@ -1497,62 +1557,30 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1497
1557
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
1498
1558
// later, at which point a suitable error will be emitted.
1499
1559
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
+ }
1501
1566
break ;
1502
1567
}
1503
1568
LifetimeRibKind :: AnonymousReportError | LifetimeRibKind :: Item => {
1504
1569
// FIXME(cjgillot) This resolution is wrong, but this does not matter
1505
1570
// since these cases are erroneous anyway. Lifetime resolution should
1506
1571
// 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
+ }
1508
1577
break ;
1509
1578
}
1510
1579
_ => { }
1511
1580
}
1512
1581
}
1513
1582
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 {
1556
1584
self . r . lint_buffer . buffer_lint_with_diagnostic (
1557
1585
lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS ,
1558
1586
segment_id,
@@ -2155,7 +2183,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
2155
2183
// Dummy self type for better errors if `Self` is used in the trait path.
2156
2184
this. with_self_rib ( Res :: SelfTy { trait_ : None , alias_to : None } , |this| {
2157
2185
this. with_lifetime_rib (
2158
- LifetimeRibKind :: AnonymousCreateParameter ( item_id) ,
2186
+ LifetimeRibKind :: AnonymousCreateParameter {
2187
+ binder : item_id,
2188
+ report_in_path : true
2189
+ } ,
2159
2190
|this| {
2160
2191
// Resolve the trait reference, if necessary.
2161
2192
this. with_optional_trait_ref (
0 commit comments