@@ -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 (
@@ -227,25 +229,30 @@ fn rematch_object<'tcx>(
227229 goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
228230 mut nested : Vec < PredicateObligation < ' tcx > > ,
229231) -> SelectionResult < ' tcx , Selection < ' tcx > > {
230- let self_ty = goal. predicate . self_ty ( ) ;
231- let ty:: Dynamic ( data, _, source_kind) = * self_ty. kind ( ) else { bug ! ( ) } ;
232- let source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , self_ty) ;
233-
234- let ( is_upcasting, target_trait_ref_unnormalized) = if Some ( goal. predicate . def_id ( ) )
235- == infcx. tcx . lang_items ( ) . unsize_trait ( )
236- {
237- assert_eq ! ( source_kind, ty:: Dyn , "cannot upcast dyn*" ) ;
238- if let ty:: Dynamic ( data, _, ty:: Dyn ) = goal. predicate . trait_ref . substs . type_at ( 1 ) . kind ( ) {
239- // FIXME: We also need to ensure that the source lifetime outlives the
240- // target lifetime. This doesn't matter for codegen, though, and only
241- // *really* matters if the goal's certainty is ambiguous.
242- ( true , data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , self_ty) )
232+ let a_ty = structurally_normalize ( goal. predicate . self_ty ( ) , infcx, goal. param_env , & mut nested) ;
233+ let ty:: Dynamic ( data, _, source_kind) = * a_ty. kind ( ) else { bug ! ( ) } ;
234+ let source_trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , a_ty) ;
235+
236+ let ( is_upcasting, target_trait_ref_unnormalized) =
237+ if Some ( goal. predicate . def_id ( ) ) == infcx. tcx . lang_items ( ) . unsize_trait ( ) {
238+ assert_eq ! ( source_kind, ty:: Dyn , "cannot upcast dyn*" ) ;
239+ let b_ty = structurally_normalize (
240+ goal. predicate . trait_ref . substs . type_at ( 1 ) ,
241+ infcx,
242+ goal. param_env ,
243+ & mut nested,
244+ ) ;
245+ if let ty:: Dynamic ( data, _, ty:: Dyn ) = * b_ty. kind ( ) {
246+ // FIXME: We also need to ensure that the source lifetime outlives the
247+ // target lifetime. This doesn't matter for codegen, though, and only
248+ // *really* matters if the goal's certainty is ambiguous.
249+ ( true , data. principal ( ) . unwrap ( ) . with_self_ty ( infcx. tcx , a_ty) )
250+ } else {
251+ bug ! ( )
252+ }
243253 } else {
244- bug ! ( )
245- }
246- } else {
247- ( false , ty:: Binder :: dummy ( goal. predicate . trait_ref ) )
248- } ;
254+ ( false , ty:: Binder :: dummy ( goal. predicate . trait_ref ) )
255+ } ;
249256
250257 let mut target_trait_ref = None ;
251258 for candidate_trait_ref in supertraits ( infcx. tcx , source_trait_ref) {
@@ -445,3 +452,22 @@ fn rematch_unsize<'tcx>(
445452
446453 Ok ( Some ( ImplSource :: Builtin ( nested) ) )
447454}
455+
456+ fn structurally_normalize < ' tcx > (
457+ ty : Ty < ' tcx > ,
458+ infcx : & InferCtxt < ' tcx > ,
459+ param_env : ty:: ParamEnv < ' tcx > ,
460+ nested : & mut Vec < PredicateObligation < ' tcx > > ,
461+ ) -> Ty < ' tcx > {
462+ if matches ! ( ty. kind( ) , ty:: Alias ( ..) ) {
463+ let mut engine = <dyn TraitEngine < ' tcx > >:: new ( infcx) ;
464+ let normalized_ty = infcx
465+ . at ( & ObligationCause :: dummy ( ) , param_env)
466+ . structurally_normalize ( ty, & mut * engine)
467+ . expect ( "normalization shouldn't fail if we got to here" ) ;
468+ nested. extend ( engine. pending_obligations ( ) ) ;
469+ normalized_ty
470+ } else {
471+ ty
472+ }
473+ }
0 commit comments