@@ -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 (
@@ -227,25 +229,30 @@ fn rematch_object<'tcx>(
227
229
goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
228
230
mut nested : Vec < PredicateObligation < ' tcx > > ,
229
231
) -> 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
+ }
243
253
} 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
+ } ;
249
256
250
257
let mut target_trait_ref = None ;
251
258
for candidate_trait_ref in supertraits ( infcx. tcx , source_trait_ref) {
@@ -445,3 +452,22 @@ fn rematch_unsize<'tcx>(
445
452
446
453
Ok ( Some ( ImplSource :: Builtin ( nested) ) )
447
454
}
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