@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
55use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
66use rustc_infer:: traits:: util:: supertraits;
77use rustc_infer:: traits:: {
8- Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult ,
8+ Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult , TraitEngine ,
99} ;
1010use rustc_middle:: traits:: solve:: { CanonicalInput , Certainty , Goal } ;
1111use rustc_middle:: traits:: {
@@ -20,6 +20,8 @@ use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree};
2020use crate :: solve:: inspect:: ProofTreeBuilder ;
2121use crate :: solve:: search_graph:: OverflowHandler ;
2222use crate :: traits:: vtable:: { count_own_vtable_entries, prepare_vtable_segments, VtblSegment } ;
23+ use crate :: traits:: StructurallyNormalizeExt ;
24+ use crate :: traits:: TraitEngineExt ;
2325
2426pub trait InferCtxtSelectExt < ' tcx > {
2527 fn select_in_new_trait_solver (
@@ -228,18 +230,24 @@ fn rematch_object<'tcx>(
228230 goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
229231 mut nested : Vec < PredicateObligation < ' tcx > > ,
230232) -> SelectionResult < ' tcx , Selection < ' tcx > > {
231- let self_ty = goal. predicate . self_ty ( ) ;
232- let ty:: Dynamic ( data, _, source_kind) = * self_ty . kind ( ) else { bug ! ( ) } ;
233- let source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , self_ty ) ;
233+ let a_ty = structurally_normalize ( goal. predicate . self_ty ( ) , infcx , goal . param_env , & mut nested ) ;
234+ let ty:: Dynamic ( data, _, source_kind) = * a_ty . kind ( ) else { bug ! ( ) } ;
235+ let source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , a_ty ) ;
234236
235237 let ( is_upcasting, target_trait_ref_unnormalized) =
236238 if Some ( goal. predicate . def_id ( ) ) == infcx. tcx . lang_items ( ) . unsize_trait ( ) {
237239 assert_eq ! ( source_kind, ty:: Dyn , "cannot upcast dyn*" ) ;
238- if let ty:: Dynamic ( data, _, ty:: Dyn ) = goal. predicate . trait_ref . args . type_at ( 1 ) . kind ( ) {
240+ let b_ty = structurally_normalize (
241+ goal. predicate . trait_ref . args . type_at ( 1 ) ,
242+ infcx,
243+ goal. param_env ,
244+ & mut nested,
245+ ) ;
246+ if let ty:: Dynamic ( data, _, ty:: Dyn ) = * b_ty. kind ( ) {
239247 // FIXME: We also need to ensure that the source lifetime outlives the
240248 // target lifetime. This doesn't matter for codegen, though, and only
241249 // *really* matters if the goal's certainty is ambiguous.
242- ( true , data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , self_ty ) )
250+ ( true , data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , a_ty ) )
243251 } else {
244252 bug ! ( )
245253 }
@@ -447,3 +455,22 @@ fn rematch_unsize<'tcx>(
447455
448456 Ok ( Some ( ImplSource :: Builtin ( nested) ) )
449457}
458+
459+ fn structurally_normalize < ' tcx > (
460+ ty : Ty < ' tcx > ,
461+ infcx : & InferCtxt < ' tcx > ,
462+ param_env : ty:: ParamEnv < ' tcx > ,
463+ nested : & mut Vec < PredicateObligation < ' tcx > > ,
464+ ) -> Ty < ' tcx > {
465+ if matches ! ( ty. kind( ) , ty:: Alias ( ..) ) {
466+ let mut engine = <dyn TraitEngine < ' tcx > >:: new ( infcx) ;
467+ let normalized_ty = infcx
468+ . at ( & ObligationCause :: dummy ( ) , param_env)
469+ . structurally_normalize ( ty, & mut * engine)
470+ . expect ( "normalization shouldn't fail if we got to here" ) ;
471+ nested. extend ( engine. pending_obligations ( ) ) ;
472+ normalized_ty
473+ } else {
474+ ty
475+ }
476+ }
0 commit comments