@@ -4,21 +4,23 @@ use rustc_hir::def_id::DefId;
44use  rustc_infer:: infer:: { DefineOpaqueTypes ,  InferCtxt ,  InferOk } ; 
55use  rustc_infer:: traits:: util:: supertraits; 
66use  rustc_infer:: traits:: { 
7-     Obligation ,  PolyTraitObligation ,  PredicateObligation ,  Selection ,  SelectionResult , 
7+     Obligation ,  PolyTraitObligation ,  PredicateObligation ,  Selection ,  SelectionResult ,   TraitEngine , 
88} ; 
99use  rustc_middle:: traits:: solve:: { CanonicalInput ,  Certainty ,  Goal } ; 
1010use  rustc_middle:: traits:: { 
1111    ImplSource ,  ImplSourceObjectData ,  ImplSourceTraitUpcastingData ,  ImplSourceUserDefinedData , 
1212    ObligationCause ,  SelectionError , 
1313} ; 
14- use  rustc_middle:: ty:: { self ,  TyCtxt } ; 
14+ use  rustc_middle:: ty:: { self ,  Ty ,   TyCtxt } ; 
1515use  rustc_span:: DUMMY_SP ; 
1616
1717use  crate :: solve:: assembly:: { BuiltinImplSource ,  Candidate ,  CandidateSource } ; 
1818use  crate :: solve:: eval_ctxt:: { EvalCtxt ,  GenerateProofTree } ; 
1919use  crate :: solve:: inspect:: ProofTreeBuilder ; 
2020use  crate :: solve:: search_graph:: OverflowHandler ; 
2121use  crate :: traits:: vtable:: { count_own_vtable_entries,  prepare_vtable_segments,  VtblSegment } ; 
22+ use  crate :: traits:: StructurallyNormalizeExt ; 
23+ use  crate :: traits:: TraitEngineExt ; 
2224
2325pub  trait  InferCtxtSelectExt < ' tcx >  { 
2426    fn  select_in_new_trait_solver ( 
@@ -220,25 +222,33 @@ fn rematch_object<'tcx>(
220222    goal :  Goal < ' tcx ,  ty:: TraitPredicate < ' tcx > > , 
221223    mut  nested :  Vec < PredicateObligation < ' tcx > > , 
222224)  -> SelectionResult < ' tcx ,  Selection < ' tcx > >  { 
223-     let  self_ty  = goal. predicate . self_ty ( ) ; 
224-     let  ty:: Dynamic ( data,  _,  source_kind)  = * self_ty . kind ( ) 
225+     let  a_ty  = structurally_normalize ( goal. predicate . self_ty ( ) ,  infcx ,  goal . param_env ,   & mut  nested ) ; 
226+     let  ty:: Dynamic ( data,  _,  source_kind)  = * a_ty . kind ( ) 
225227    else  { 
226228        bug ! ( ) 
227229    } ; 
228-     let  source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx ,  self_ty) ; 
229- 
230-     let  ( is_upcasting,  target_trait_ref_unnormalized)  = if  Some ( goal. predicate . def_id ( ) ) 
231-         == infcx. tcx . lang_items ( ) . unsize_trait ( ) 
232-     { 
233-         assert_eq ! ( source_kind,  ty:: Dyn ,  "cannot upcast dyn*" ) ; 
234-         if  let  ty:: Dynamic ( data,  _,  ty:: Dyn )  = goal. predicate . trait_ref . substs . type_at ( 1 ) . kind ( )  { 
235-             ( true ,  data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx ,  self_ty) ) 
230+     let  source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx ,  a_ty) ; 
231+ 
232+     let  ( is_upcasting,  target_trait_ref_unnormalized)  =
233+         if  Some ( goal. predicate . def_id ( ) )  == infcx. tcx . lang_items ( ) . unsize_trait ( )  { 
234+             assert_eq ! ( source_kind,  ty:: Dyn ,  "cannot upcast dyn*" ) ; 
235+             let  b_ty = structurally_normalize ( 
236+                 goal. predicate . trait_ref . substs . type_at ( 1 ) , 
237+                 infcx, 
238+                 goal. param_env , 
239+                 & mut  nested, 
240+             ) ; 
241+             if  let  ty:: Dynamic ( data,  _,  ty:: Dyn )  = * b_ty. kind ( )  { 
242+                 // FIXME: We also need to ensure that the source lifetime outlives the 
243+                 // target lifetime. This doesn't matter for codegen, though, and only 
244+                 // *really* matters if the goal's certainty is ambiguous. 
245+                 ( true ,  data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx ,  a_ty) ) 
246+             }  else  { 
247+                 bug ! ( ) 
248+             } 
236249        }  else  { 
237-             bug ! ( ) 
238-         } 
239-     }  else  { 
240-         ( false ,  ty:: Binder :: dummy ( goal. predicate . trait_ref ) ) 
241-     } ; 
250+             ( false ,  ty:: Binder :: dummy ( goal. predicate . trait_ref ) ) 
251+         } ; 
242252
243253    let  mut  target_trait_ref = None ; 
244254    for  candidate_trait_ref in  supertraits ( infcx. tcx ,  source_trait_ref)  { 
@@ -305,3 +315,22 @@ fn rematch_object<'tcx>(
305315        ImplSource :: Object ( ImplSourceObjectData  {  vtable_base,  nested } ) 
306316    } ) ) 
307317} 
318+ 
319+ fn  structurally_normalize < ' tcx > ( 
320+     ty :  Ty < ' tcx > , 
321+     infcx :  & InferCtxt < ' tcx > , 
322+     param_env :  ty:: ParamEnv < ' tcx > , 
323+     nested :  & mut  Vec < PredicateObligation < ' tcx > > , 
324+ )  -> Ty < ' tcx >  { 
325+     if  matches ! ( ty. kind( ) ,  ty:: Alias ( ..) )  { 
326+         let  mut  engine = <dyn  TraitEngine < ' tcx > >:: new ( infcx) ; 
327+         let  normalized_ty = infcx
328+             . at ( & ObligationCause :: dummy ( ) ,  param_env) 
329+             . structurally_normalize ( ty,  & mut  * engine) 
330+             . expect ( "normalization shouldn't fail if we got to here" ) ; 
331+         nested. extend ( engine. pending_obligations ( ) ) ; 
332+         normalized_ty
333+     }  else  { 
334+         ty
335+     } 
336+ } 
0 commit comments