@@ -9,7 +9,7 @@ use crate::hir::def::{Res, DefKind};
9
9
use crate :: hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
10
10
use crate :: hir:: map:: Map ;
11
11
use crate :: hir:: ptr:: P ;
12
- use crate :: hir:: { GenericArg , GenericParam , ItemLocalId , LifetimeName , Node , ParamName } ;
12
+ use crate :: hir:: { GenericArg , GenericParam , ItemLocalId , LifetimeName , Node , ParamName , QPath } ;
13
13
use crate :: ty:: { self , DefIdTree , GenericParamDefKind , TyCtxt } ;
14
14
15
15
use crate :: rustc:: lint;
@@ -1458,10 +1458,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1458
1458
}
1459
1459
1460
1460
// helper method to issue suggestions from `fn rah<'a>(&'a T)` to `fn rah(&T)`
1461
+ // or from `fn rah<'a>(T<'a>)` to `fn rah(T<'_>)`
1461
1462
fn suggest_eliding_single_use_lifetime (
1462
1463
& self , err : & mut DiagnosticBuilder < ' _ > , def_id : DefId , lifetime : & hir:: Lifetime
1463
1464
) {
1464
- // FIXME: future work: also suggest `impl Foo<'_>` for `impl<'a> Foo<'a>`
1465
1465
let name = lifetime. name . ident ( ) ;
1466
1466
let mut remove_decl = None ;
1467
1467
if let Some ( parent_def_id) = self . tcx . parent ( def_id) {
@@ -1471,18 +1471,38 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1471
1471
}
1472
1472
1473
1473
let mut remove_use = None ;
1474
+ let mut elide_use = None ;
1474
1475
let mut find_arg_use_span = |inputs : & hir:: HirVec < hir:: Ty > | {
1475
1476
for input in inputs {
1476
- if let hir:: TyKind :: Rptr ( lt, _) = input. node {
1477
- if lt. name . ident ( ) == name {
1478
- // include the trailing whitespace between the ampersand and the type name
1479
- let lt_through_ty_span = lifetime. span . to ( input. span . shrink_to_hi ( ) ) ;
1480
- remove_use = Some (
1481
- self . tcx . sess . source_map ( )
1482
- . span_until_non_whitespace ( lt_through_ty_span)
1483
- ) ;
1484
- break ;
1477
+ match input. node {
1478
+ hir:: TyKind :: Rptr ( lt, _) => {
1479
+ if lt. name . ident ( ) == name {
1480
+ // include the trailing whitespace between the lifetime and type names
1481
+ let lt_through_ty_span = lifetime. span . to ( input. span . shrink_to_hi ( ) ) ;
1482
+ remove_use = Some (
1483
+ self . tcx . sess . source_map ( )
1484
+ . span_until_non_whitespace ( lt_through_ty_span)
1485
+ ) ;
1486
+ break ;
1487
+ }
1485
1488
}
1489
+ hir:: TyKind :: Path ( ref qpath) => {
1490
+ if let QPath :: Resolved ( _, path) = qpath {
1491
+
1492
+ let last_segment = & path. segments [ path. segments . len ( ) -1 ] ;
1493
+ let generics = last_segment. generic_args ( ) ;
1494
+ for arg in generics. args . iter ( ) {
1495
+ if let GenericArg :: Lifetime ( lt) = arg {
1496
+ if lt. name . ident ( ) == name {
1497
+ elide_use = Some ( lt. span ) ;
1498
+ break ;
1499
+ }
1500
+ }
1501
+ }
1502
+ break ;
1503
+ }
1504
+ } ,
1505
+ _ => { }
1486
1506
}
1487
1507
}
1488
1508
} ;
@@ -1506,24 +1526,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1506
1526
}
1507
1527
}
1508
1528
1509
- if let ( Some ( decl_span) , Some ( use_span) ) = ( remove_decl, remove_use) {
1510
- // if both declaration and use deletion spans start at the same
1511
- // place ("start at" because the latter includes trailing
1512
- // whitespace), then this is an in-band lifetime
1513
- if decl_span. shrink_to_lo ( ) == use_span. shrink_to_lo ( ) {
1514
- err. span_suggestion (
1515
- use_span,
1516
- "elide the single-use lifetime" ,
1517
- String :: new ( ) ,
1518
- Applicability :: MachineApplicable ,
1519
- ) ;
1520
- } else {
1529
+ let msg = "elide the single-use lifetime" ;
1530
+ match ( remove_decl, remove_use, elide_use) {
1531
+ ( Some ( decl_span) , Some ( use_span) , None ) => {
1532
+ // if both declaration and use deletion spans start at the same
1533
+ // place ("start at" because the latter includes trailing
1534
+ // whitespace), then this is an in-band lifetime
1535
+ if decl_span. shrink_to_lo ( ) == use_span. shrink_to_lo ( ) {
1536
+ err. span_suggestion (
1537
+ use_span,
1538
+ msg,
1539
+ String :: new ( ) ,
1540
+ Applicability :: MachineApplicable ,
1541
+ ) ;
1542
+ } else {
1543
+ err. multipart_suggestion (
1544
+ msg,
1545
+ vec ! [ ( decl_span, String :: new( ) ) , ( use_span, String :: new( ) ) ] ,
1546
+ Applicability :: MachineApplicable ,
1547
+ ) ;
1548
+ }
1549
+ }
1550
+ ( Some ( decl_span) , None , Some ( use_span) ) => {
1521
1551
err. multipart_suggestion (
1522
- "elide the single-use lifetime" ,
1523
- vec ! [ ( decl_span, String :: new( ) ) , ( use_span, String :: new ( ) ) ] ,
1552
+ msg ,
1553
+ vec ! [ ( decl_span, String :: new( ) ) , ( use_span, "'_" . to_owned ( ) ) ] ,
1524
1554
Applicability :: MachineApplicable ,
1525
1555
) ;
1526
1556
}
1557
+ _ => { }
1527
1558
}
1528
1559
}
1529
1560
0 commit comments