@@ -2299,19 +2299,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2299
2299
let span = lifetime_refs[ 0 ] . span ;
2300
2300
let mut late_depth = 0 ;
2301
2301
let mut scope = self . scope ;
2302
+ let mut lifetime_names = FxHashSet :: default ( ) ;
2302
2303
let error = loop {
2303
2304
match * scope {
2304
2305
// Do not assign any resolution, it will be inferred.
2305
2306
Scope :: Body { .. } => return ,
2306
2307
2307
2308
Scope :: Root => break None ,
2308
2309
2309
- Scope :: Binder { s, .. } => {
2310
+ Scope :: Binder { s, ref lifetimes, .. } => {
2311
+ // collect named lifetimes for suggestions
2312
+ for name in lifetimes. keys ( ) {
2313
+ if let hir:: ParamName :: Plain ( name) = name {
2314
+ lifetime_names. insert ( * name) ;
2315
+ }
2316
+ }
2310
2317
late_depth += 1 ;
2311
2318
scope = s;
2312
2319
}
2313
2320
2314
- Scope :: Elision { ref elide, .. } => {
2321
+ Scope :: Elision { ref elide, ref s , .. } => {
2315
2322
let lifetime = match * elide {
2316
2323
Elide :: FreshLateAnon ( ref counter) => {
2317
2324
for lifetime_ref in lifetime_refs {
@@ -2321,7 +2328,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2321
2328
return ;
2322
2329
}
2323
2330
Elide :: Exact ( l) => l. shifted ( late_depth) ,
2324
- Elide :: Error ( ref e) => break Some ( e) ,
2331
+ Elide :: Error ( ref e) => {
2332
+ if let Scope :: Binder { ref lifetimes, .. } = s {
2333
+ // collect named lifetimes for suggestions
2334
+ for name in lifetimes. keys ( ) {
2335
+ if let hir:: ParamName :: Plain ( name) = name {
2336
+ lifetime_names. insert ( * name) ;
2337
+ }
2338
+ }
2339
+ }
2340
+ break Some ( e) ;
2341
+ }
2325
2342
} ;
2326
2343
for lifetime_ref in lifetime_refs {
2327
2344
self . insert_lifetime ( lifetime_ref, lifetime) ;
@@ -2344,7 +2361,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2344
2361
}
2345
2362
}
2346
2363
if add_label {
2347
- add_missing_lifetime_specifiers_label ( & mut err, span, lifetime_refs. len ( ) ) ;
2364
+ add_missing_lifetime_specifiers_label (
2365
+ & mut err,
2366
+ span,
2367
+ lifetime_refs. len ( ) ,
2368
+ & lifetime_names,
2369
+ self . tcx . sess . source_map ( ) . span_to_snippet ( span) . ok ( ) . as_ref ( ) . map ( |s| s. as_str ( ) ) ,
2370
+ ) ;
2348
2371
}
2349
2372
2350
2373
err. emit ( ) ;
@@ -2885,10 +2908,23 @@ fn add_missing_lifetime_specifiers_label(
2885
2908
err : & mut DiagnosticBuilder < ' _ > ,
2886
2909
span : Span ,
2887
2910
count : usize ,
2911
+ lifetime_names : & FxHashSet < ast:: Ident > ,
2912
+ snippet : Option < & str > ,
2888
2913
) {
2889
2914
if count > 1 {
2890
2915
err. span_label ( span, format ! ( "expected {} lifetime parameters" , count) ) ;
2916
+ } else if let ( 1 , Some ( name) , Some ( "&" ) ) = (
2917
+ lifetime_names. len ( ) ,
2918
+ lifetime_names. iter ( ) . next ( ) ,
2919
+ snippet,
2920
+ ) {
2921
+ err. span_suggestion (
2922
+ span,
2923
+ "consider using the named lifetime" ,
2924
+ format ! ( "&{} " , name) ,
2925
+ Applicability :: MaybeIncorrect ,
2926
+ ) ;
2891
2927
} else {
2892
2928
err. span_label ( span, "expected lifetime parameter" ) ;
2893
- } ;
2929
+ }
2894
2930
}
0 commit comments