@@ -4,21 +4,23 @@ use rustc_hir::def_id::DefId;
44use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
55use rustc_infer:: traits:: util:: supertraits;
66use rustc_infer:: traits:: {
7- Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult ,
7+ Obligation , PolyTraitObligation , PredicateObligation , Selection , SelectionResult , TraitEngine ,
88} ;
99use rustc_middle:: traits:: solve:: { CanonicalInput , Certainty , Goal } ;
1010use rustc_middle:: traits:: {
1111 ImplSource , ImplSourceObjectData , ImplSourceTraitUpcastingData , ImplSourceUserDefinedData ,
1212 ObligationCause , SelectionError ,
1313} ;
14- use rustc_middle:: ty:: { self , TyCtxt } ;
14+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1515use rustc_span:: DUMMY_SP ;
1616
1717use crate :: solve:: assembly:: { BuiltinImplSource , Candidate , CandidateSource } ;
1818use crate :: solve:: eval_ctxt:: { EvalCtxt , GenerateProofTree } ;
1919use crate :: solve:: inspect:: ProofTreeBuilder ;
2020use crate :: solve:: search_graph:: OverflowHandler ;
2121use crate :: traits:: vtable:: { count_own_vtable_entries, prepare_vtable_segments, VtblSegment } ;
22+ use crate :: traits:: StructurallyNormalizeExt ;
23+ use crate :: traits:: TraitEngineExt ;
2224
2325pub trait InferCtxtSelectExt < ' tcx > {
2426 fn select_in_new_trait_solver (
@@ -220,25 +222,33 @@ fn rematch_object<'tcx>(
220222 goal : Goal < ' tcx , ty:: TraitPredicate < ' tcx > > ,
221223 mut nested : Vec < PredicateObligation < ' tcx > > ,
222224) -> 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 ( )
225227 else {
226228 bug ! ( )
227229 } ;
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+ }
236249 } 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+ } ;
242252
243253 let mut target_trait_ref = None ;
244254 for candidate_trait_ref in supertraits ( infcx. tcx , source_trait_ref) {
@@ -305,3 +315,22 @@ fn rematch_object<'tcx>(
305315 ImplSource :: Object ( ImplSourceObjectData { vtable_base, nested } )
306316 } ) )
307317}
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