@@ -27,6 +27,8 @@ use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
2727use rustc_span:: symbol:: sym;
2828use rustc_span:: { DUMMY_SP , Symbol } ;
2929use rustc_target:: abi:: FIRST_VARIANT ;
30+ use rustc_trait_selection:: infer:: TyCtxtInferExt ;
31+ use rustc_trait_selection:: traits:: { ObligationCause , ObligationCtxt } ;
3032use tracing:: { debug, info} ;
3133
3234use crate :: assert_module_sources:: CguReuse ;
@@ -101,6 +103,38 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
101103 bx. sext ( cmp, ret_ty)
102104}
103105
106+ /// Codegen takes advantage of the additional assumption, where if the
107+ /// principal trait def id of what's being casted doesn't change,
108+ /// then we don't need to adjust the vtable at all. This
109+ /// corresponds to the fact that `dyn Tr<A>: Unsize<dyn Tr<B>>`
110+ /// requires that `A = B`; we don't allow *upcasting* objects
111+ /// between the same trait with different args. If we, for
112+ /// some reason, were to relax the `Unsize` trait, it could become
113+ /// unsound, so let's validate here that the trait refs are subtypes.
114+ pub fn validate_trivial_unsize < ' tcx > (
115+ tcx : TyCtxt < ' tcx > ,
116+ data_a : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
117+ data_b : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
118+ ) -> bool {
119+ match ( data_a. principal ( ) , data_b. principal ( ) ) {
120+ ( Some ( principal_a) , Some ( principal_b) ) => {
121+ let infcx = tcx. infer_ctxt ( ) . build ( ) ;
122+ let ocx = ObligationCtxt :: new ( & infcx) ;
123+ let Ok ( ( ) ) = ocx. sub (
124+ & ObligationCause :: dummy ( ) ,
125+ ty:: ParamEnv :: reveal_all ( ) ,
126+ principal_a,
127+ principal_b,
128+ ) else {
129+ return false ;
130+ } ;
131+ ocx. select_all_or_error ( ) . is_empty ( )
132+ }
133+ ( None , None ) => true ,
134+ _ => false ,
135+ }
136+ }
137+
104138/// Retrieves the information we are losing (making dynamic) in an unsizing
105139/// adjustment.
106140///
@@ -133,12 +167,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
133167 // between the same trait with different args. If we, for
134168 // some reason, were to relax the `Unsize` trait, it could become
135169 // unsound, so let's assert here that the trait refs are *equal*.
136- //
137- // We can use `assert_eq` because the binders should have been anonymized,
138- // and because higher-ranked equality now requires the binders are equal.
139- debug_assert_eq ! (
140- data_a. principal( ) ,
141- data_b. principal( ) ,
170+ debug_assert ! (
171+ validate_trivial_unsize( cx. tcx( ) , data_a, data_b) ,
142172 "NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"
143173 ) ;
144174
0 commit comments