@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
5
5
use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
6
6
use rustc_infer:: traits:: util:: supertraits;
7
7
use rustc_infer:: traits:: {
8
- Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult ,
8
+ Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult , TraitEngine ,
9
9
} ;
10
10
use rustc_middle:: traits:: solve:: { CanonicalInput , Certainty , Goal } ;
11
11
use rustc_middle:: traits:: {
@@ -20,6 +20,8 @@ use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree};
20
20
use crate :: solve:: inspect:: ProofTreeBuilder ;
21
21
use crate :: solve:: search_graph:: OverflowHandler ;
22
22
use crate :: traits:: vtable:: { count_own_vtable_entries, prepare_vtable_segments, VtblSegment } ;
23
+ use crate :: traits:: StructurallyNormalizeExt ;
24
+ use crate :: traits:: TraitEngineExt ;
23
25
24
26
pub trait InferCtxtSelectExt < ' tcx > {
25
27
fn select_in_new_trait_solver (
@@ -228,18 +230,24 @@ fn rematch_object<'tcx>(
228
230
goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
229
231
mut nested : Vec < PredicateObligation < ' tcx > > ,
230
232
) -> 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 ) ;
234
236
235
237
let ( is_upcasting, target_trait_ref_unnormalized) =
236
238
if Some ( goal. predicate . def_id ( ) ) == infcx. tcx . lang_items ( ) . unsize_trait ( ) {
237
239
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 ( ) {
239
247
// FIXME: We also need to ensure that the source lifetime outlives the
240
248
// target lifetime. This doesn't matter for codegen, though, and only
241
249
// *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 ) )
243
251
} else {
244
252
bug ! ( )
245
253
}
@@ -447,3 +455,22 @@ fn rematch_unsize<'tcx>(
447
455
448
456
Ok ( Some ( ImplSource :: Builtin ( nested) ) )
449
457
}
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