@@ -5,12 +5,13 @@ use rustc_hir as hir;
5
5
use rustc_hir:: intravisit:: Visitor ;
6
6
use rustc_index:: IndexSlice ;
7
7
use rustc_infer:: infer:: NllRegionVariableOrigin ;
8
+ use rustc_middle:: middle:: resolve_bound_vars:: ObjectLifetimeDefault ;
8
9
use rustc_middle:: mir:: {
9
10
Body , CallSource , CastKind , ConstraintCategory , FakeReadCause , Local , LocalInfo , Location ,
10
11
Operand , Place , Rvalue , Statement , StatementKind , TerminatorKind ,
11
12
} ;
12
13
use rustc_middle:: ty:: adjustment:: PointerCoercion ;
13
- use rustc_middle:: ty:: { self , RegionVid , TyCtxt } ;
14
+ use rustc_middle:: ty:: { self , RegionVid , Ty , TyCtxt } ;
14
15
use rustc_span:: symbol:: { kw, Symbol } ;
15
16
use rustc_span:: { sym, DesugaringKind , Span } ;
16
17
use rustc_trait_selection:: traits:: error_reporting:: FindExprBySpan ;
@@ -290,12 +291,69 @@ impl<'tcx> BorrowExplanation<'tcx> {
290
291
}
291
292
}
292
293
294
+ if let ConstraintCategory :: Cast { unsize_to : Some ( unsize_ty) } = category {
295
+ self . add_object_lifetime_default_note ( tcx, err, unsize_ty) ;
296
+ }
293
297
self . add_lifetime_bound_suggestion_to_diagnostic ( err, & category, span, region_name) ;
294
298
}
295
299
_ => { }
296
300
}
297
301
}
298
302
303
+ fn add_object_lifetime_default_note (
304
+ & self ,
305
+ tcx : TyCtxt < ' tcx > ,
306
+ err : & mut Diagnostic ,
307
+ unsize_ty : Ty < ' tcx > ,
308
+ ) {
309
+ if let ty:: Adt ( def, args) = unsize_ty. kind ( ) {
310
+ // We try to elaborate the object lifetime defaults and present those to the user. This should
311
+ // make it clear where the region constraint is coming from.
312
+ let generics = tcx. generics_of ( def. did ( ) ) ;
313
+
314
+ let mut has_dyn = false ;
315
+ let mut failed = false ;
316
+
317
+ let elaborated_args = std:: iter:: zip ( * args, & generics. params ) . map ( |( arg, param) | {
318
+ if let Some ( ty:: Dynamic ( obj, _, ty:: DynKind :: Dyn ) ) = arg. as_type ( ) . map ( Ty :: kind) {
319
+ let default = tcx. object_lifetime_default ( param. def_id ) ;
320
+
321
+ let re_static = tcx. lifetimes . re_static ;
322
+
323
+ let implied_region = match default {
324
+ // This is not entirely precise.
325
+ ObjectLifetimeDefault :: Empty => re_static,
326
+ ObjectLifetimeDefault :: Ambiguous => {
327
+ failed = true ;
328
+ re_static
329
+ }
330
+ ObjectLifetimeDefault :: Param ( param_def_id) => {
331
+ let index = generics. param_def_id_to_index [ & param_def_id] as usize ;
332
+ args. get ( index) . and_then ( |arg| arg. as_region ( ) ) . unwrap_or_else ( || {
333
+ failed = true ;
334
+ re_static
335
+ } )
336
+ }
337
+ ObjectLifetimeDefault :: Static => re_static,
338
+ } ;
339
+
340
+ has_dyn = true ;
341
+
342
+ Ty :: new_dynamic ( tcx, obj, implied_region, ty:: DynKind :: Dyn ) . into ( )
343
+ } else {
344
+ arg
345
+ }
346
+ } ) ;
347
+ let elaborated_ty = Ty :: new_adt ( tcx, * def, tcx. mk_args_from_iter ( elaborated_args) ) ;
348
+
349
+ if has_dyn && !failed {
350
+ err. note ( format ! (
351
+ "due to object lifetime defaults, `{unsize_ty}` actually means `{elaborated_ty}`"
352
+ ) ) ;
353
+ }
354
+ }
355
+ }
356
+
299
357
fn add_lifetime_bound_suggestion_to_diagnostic (
300
358
& self ,
301
359
err : & mut Diagnostic ,
0 commit comments