@@ -5,12 +5,13 @@ use rustc_hir as hir;
55use rustc_hir:: intravisit:: Visitor ;
66use rustc_index:: IndexSlice ;
77use rustc_infer:: infer:: NllRegionVariableOrigin ;
8+ use rustc_middle:: middle:: resolve_bound_vars:: ObjectLifetimeDefault ;
89use rustc_middle:: mir:: {
910 Body , CallSource , CastKind , ConstraintCategory , FakeReadCause , Local , LocalInfo , Location ,
1011 Operand , Place , Rvalue , Statement , StatementKind , TerminatorKind ,
1112} ;
1213use rustc_middle:: ty:: adjustment:: PointerCoercion ;
13- use rustc_middle:: ty:: { self , RegionVid , TyCtxt } ;
14+ use rustc_middle:: ty:: { self , RegionVid , Ty , TyCtxt } ;
1415use rustc_span:: symbol:: { kw, Symbol } ;
1516use rustc_span:: { sym, DesugaringKind , Span } ;
1617use rustc_trait_selection:: traits:: error_reporting:: FindExprBySpan ;
@@ -290,12 +291,69 @@ impl<'tcx> BorrowExplanation<'tcx> {
290291 }
291292 }
292293
294+ if let ConstraintCategory :: Cast { unsize_to : Some ( unsize_ty) } = category {
295+ self . add_object_lifetime_default_note ( tcx, err, unsize_ty) ;
296+ }
293297 self . add_lifetime_bound_suggestion_to_diagnostic ( err, & category, span, region_name) ;
294298 }
295299 _ => { }
296300 }
297301 }
298302
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+
299357 fn add_lifetime_bound_suggestion_to_diagnostic (
300358 & self ,
301359 err : & mut Diagnostic ,
0 commit comments