@@ -4,21 +4,23 @@ use rustc_hir::def_id::DefId;
4
4
use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
5
5
use rustc_infer:: traits:: util:: supertraits;
6
6
use rustc_infer:: traits:: {
7
- Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult ,
7
+ Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult , TraitEngine ,
8
8
} ;
9
9
use rustc_middle:: traits:: solve:: { CanonicalInput , Certainty , Goal } ;
10
10
use rustc_middle:: traits:: {
11
11
ImplSource , ImplSourceObjectData , ImplSourceTraitUpcastingData , ImplSourceUserDefinedData ,
12
12
ObligationCause , SelectionError ,
13
13
} ;
14
- use rustc_middle:: ty:: { self , TyCtxt } ;
14
+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
15
15
use rustc_span:: DUMMY_SP ;
16
16
17
17
use crate :: solve:: assembly:: { BuiltinImplSource , Candidate , CandidateSource } ;
18
18
use crate :: solve:: eval_ctxt:: { EvalCtxt , GenerateProofTree } ;
19
19
use crate :: solve:: inspect:: ProofTreeBuilder ;
20
20
use crate :: solve:: search_graph:: OverflowHandler ;
21
21
use crate :: traits:: vtable:: { count_own_vtable_entries, prepare_vtable_segments, VtblSegment } ;
22
+ use crate :: traits:: StructurallyNormalizeExt ;
23
+ use crate :: traits:: TraitEngineExt ;
22
24
23
25
pub trait InferCtxtSelectExt < ' tcx > {
24
26
fn select_in_new_trait_solver (
@@ -220,25 +222,33 @@ fn rematch_object<'tcx>(
220
222
goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
221
223
mut nested : Vec < PredicateObligation < ' tcx > > ,
222
224
) -> 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 ( )
225
227
else {
226
228
bug ! ( )
227
229
} ;
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
+ }
236
249
} 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
+ } ;
242
252
243
253
let mut target_trait_ref = None ;
244
254
for candidate_trait_ref in supertraits ( infcx. tcx , source_trait_ref) {
@@ -305,3 +315,22 @@ fn rematch_object<'tcx>(
305
315
ImplSource :: Object ( ImplSourceObjectData { vtable_base, nested } )
306
316
} ) )
307
317
}
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