@@ -8,8 +8,10 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorRepor
8
8
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
9
9
use rustc_hir:: intravisit:: { walk_ty, ErasedMap , NestedVisitorMap , Visitor } ;
10
10
use rustc_hir:: { self as hir, GenericBound , Item , ItemKind , Lifetime , LifetimeName , Node , TyKind } ;
11
- use rustc_middle:: ty:: { self , AssocItemContainer , RegionKind , Ty , TypeFoldable , TypeVisitor } ;
12
- use rustc_span:: Span ;
11
+ use rustc_middle:: ty:: {
12
+ self , AssocItem , AssocItemContainer , RegionKind , Ty , TypeFoldable , TypeVisitor ,
13
+ } ;
14
+ use rustc_span:: { MultiSpan , Span } ;
13
15
14
16
impl < ' a , ' tcx > NiceRegionError < ' a , ' tcx > {
15
17
/// Print the error message for lifetime errors when the return type is a static impl Trait.
@@ -51,7 +53,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
51
53
cause. span ,
52
54
"...is captured and required to live as long as `'static` here" ,
53
55
) ;
54
- if self . find_impl_on_dyn_trait ( & mut err, param. param_ty , & assoc. container ) {
56
+ if self . find_impl_on_dyn_trait ( & mut err, param. param_ty , assoc) {
55
57
err. emit ( ) ;
56
58
return Some ( ErrorReported ) ;
57
59
} else {
@@ -131,7 +133,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
131
133
132
134
if let SubregionOrigin :: Subtype ( box TypeTrace { cause, .. } ) = & sup_origin {
133
135
if let ObligationCauseCode :: UnifyReceiver ( assoc) = & cause. code {
134
- self . find_impl_on_dyn_trait ( & mut err, param. param_ty , & assoc. container ) ;
136
+ self . find_impl_on_dyn_trait ( & mut err, param. param_ty , assoc) ;
135
137
}
136
138
}
137
139
@@ -263,7 +265,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
263
265
& self ,
264
266
err : & mut DiagnosticBuilder < ' _ > ,
265
267
ty : Ty < ' _ > ,
266
- container : & AssocItemContainer ,
268
+ assoc : & AssocItem ,
267
269
) -> bool {
268
270
let tcx = self . tcx ( ) ;
269
271
let mut suggested = false ;
@@ -272,7 +274,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
272
274
let mut v = TraitObjectVisitor ( vec ! [ ] ) ;
273
275
v. visit_ty ( ty) ;
274
276
275
- let container_id = match container {
277
+ let container_id = match assoc . container {
276
278
// When the obligation comes from an `impl Foo for dyn Bar {}`, we
277
279
// have the `DefId` of the `trait` itself, not the relevant `impl`
278
280
// block. Because of this, we have to look at all the `trait`s
@@ -284,16 +286,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
284
286
// have the `DefId` of the relevant `Item`, so we use it directly.
285
287
AssocItemContainer :: ImplContainer ( def_id) => {
286
288
if let Some ( Node :: Item ( Item { kind : ItemKind :: Impl { self_ty, .. } , .. } ) ) =
287
- tcx. hir ( ) . get_if_local ( * def_id)
289
+ tcx. hir ( ) . get_if_local ( def_id)
288
290
{
289
291
for found_did in & v. 0 {
290
292
let mut hir_v = HirTraitObjectVisitor ( vec ! [ ] , * found_did) ;
291
293
hir_v. visit_ty ( self_ty) ;
292
294
if let [ span] = & hir_v. 0 [ ..] {
295
+ let mut multi_span: MultiSpan = vec ! [ * span] . into ( ) ;
296
+ multi_span. push_span_label (
297
+ * span,
298
+ "this trait object has an implicit `'static` lifetime requirement"
299
+ . to_string ( ) ,
300
+ ) ;
301
+ multi_span. push_span_label (
302
+ assoc. ident . span ,
303
+ "the `'static` requirement is introduced when calling this method"
304
+ . to_string ( ) ,
305
+ ) ;
306
+ err. span_note (
307
+ multi_span,
308
+ & format ! (
309
+ "when using method `{}` on `{}`, an implicit `'static` \
310
+ requirement is introduced",
311
+ assoc. ident,
312
+ tcx. def_path_str( * found_did) ,
313
+ ) ,
314
+ ) ;
293
315
err. span_suggestion_verbose (
294
316
span. shrink_to_hi ( ) ,
295
- "this `impl` introduces an implicit `'static` requirement, \
296
- consider changing it",
317
+ "consider relaxing the implicit `'static` requirement" ,
297
318
" + '_" . to_string ( ) ,
298
319
Applicability :: MaybeIncorrect ,
299
320
) ;
@@ -316,24 +337,53 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
316
337
let impl_did = tcx. hir ( ) . local_def_id ( * impl_node) ;
317
338
match tcx. hir ( ) . get_if_local ( impl_did. to_def_id ( ) ) {
318
339
Some ( Node :: Item ( Item {
319
- kind : ItemKind :: Impl { self_ty, of_trait : Some ( of_trait) , .. } ,
340
+ kind : ItemKind :: Impl { self_ty, of_trait : Some ( of_trait) , items , .. } ,
320
341
..
321
- } ) ) if of_trait. trait_def_id ( ) == Some ( * container_id) => Some ( self_ty) ,
342
+ } ) ) if of_trait. trait_def_id ( ) == Some ( container_id) => Some ( (
343
+ self_ty,
344
+ // Get the ident of the method, in order to use its `Span`.
345
+ items
346
+ . iter ( )
347
+ . filter ( |item| item. ident == assoc. ident )
348
+ . map ( |item| item. ident )
349
+ . next ( )
350
+ . unwrap_or ( assoc. ident ) ,
351
+ ) ) ,
322
352
_ => None ,
323
353
}
324
354
} ) ;
325
355
326
356
// Given all the `impl`s of the relevant `trait`, look for those that are implemented for
327
357
// the trait object in the `fn` parameter type.
328
- for self_ty in impl_self_tys {
358
+ for ( self_ty, method ) in impl_self_tys {
329
359
for found_did in & v. 0 {
330
360
let mut hir_v = HirTraitObjectVisitor ( vec ! [ ] , * found_did) ;
331
361
hir_v. visit_ty ( self_ty) ;
332
362
if let [ span] = & hir_v. 0 [ ..] {
363
+ let mut multi_span: MultiSpan = vec ! [ * span] . into ( ) ;
364
+ multi_span. push_span_label (
365
+ * span,
366
+ "this trait object has an implicit `'static` lifetime requirement"
367
+ . to_string ( ) ,
368
+ ) ;
369
+ multi_span. push_span_label (
370
+ method. span ,
371
+ "the `'static` requirement is introduced when calling this method"
372
+ . to_string ( ) ,
373
+ ) ;
374
+ err. span_note (
375
+ multi_span,
376
+ & format ! (
377
+ "when using method `{}` of trait `{}` on `{}`, an implicit `'static` \
378
+ requirement is introduced",
379
+ method,
380
+ tcx. def_path_str( container_id) ,
381
+ tcx. def_path_str( * found_did) ,
382
+ ) ,
383
+ ) ;
333
384
err. span_suggestion_verbose (
334
385
span. shrink_to_hi ( ) ,
335
- "this `impl` introduces an implicit `'static` requirement, \
336
- consider changing it",
386
+ "consider relaxing the implicit `'static` requirement" ,
337
387
" + '_" . to_string ( ) ,
338
388
Applicability :: MaybeIncorrect ,
339
389
) ;
0 commit comments