@@ -9,7 +9,7 @@ use crate::hir::def::{Res, DefKind};
99use crate :: hir:: def_id:: { CrateNum , DefId , LocalDefId , LOCAL_CRATE } ;
1010use crate :: hir:: map:: Map ;
1111use 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 } ;
1313use crate :: ty:: { self , DefIdTree , GenericParamDefKind , TyCtxt } ;
1414
1515use crate :: rustc:: lint;
@@ -1458,10 +1458,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14581458 }
14591459
14601460 // 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<'_>)`
14611462 fn suggest_eliding_single_use_lifetime (
14621463 & self , err : & mut DiagnosticBuilder < ' _ > , def_id : DefId , lifetime : & hir:: Lifetime
14631464 ) {
1464- // FIXME: future work: also suggest `impl Foo<'_>` for `impl<'a> Foo<'a>`
14651465 let name = lifetime. name . ident ( ) ;
14661466 let mut remove_decl = None ;
14671467 if let Some ( parent_def_id) = self . tcx . parent ( def_id) {
@@ -1471,18 +1471,38 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14711471 }
14721472
14731473 let mut remove_use = None ;
1474+ let mut elide_use = None ;
14741475 let mut find_arg_use_span = |inputs : & hir:: HirVec < hir:: Ty > | {
14751476 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+ }
14851488 }
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+ _ => { }
14861506 }
14871507 }
14881508 } ;
@@ -1506,24 +1526,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15061526 }
15071527 }
15081528
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) ) => {
15211551 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 ( ) ) ] ,
15241554 Applicability :: MachineApplicable ,
15251555 ) ;
15261556 }
1557+ _ => { }
15271558 }
15281559 }
15291560
0 commit comments