@@ -27,6 +27,8 @@ use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
27
27
use rustc_span:: symbol:: sym;
28
28
use rustc_span:: { DUMMY_SP , Symbol } ;
29
29
use rustc_target:: abi:: FIRST_VARIANT ;
30
+ use rustc_trait_selection:: infer:: TyCtxtInferExt ;
31
+ use rustc_trait_selection:: traits:: { ObligationCause , ObligationCtxt } ;
30
32
use tracing:: { debug, info} ;
31
33
32
34
use crate :: assert_module_sources:: CguReuse ;
@@ -101,6 +103,38 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
101
103
bx. sext ( cmp, ret_ty)
102
104
}
103
105
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
+
104
138
/// Retrieves the information we are losing (making dynamic) in an unsizing
105
139
/// adjustment.
106
140
///
@@ -133,12 +167,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
133
167
// between the same trait with different args. If we, for
134
168
// some reason, were to relax the `Unsize` trait, it could become
135
169
// 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) ,
142
172
"NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"
143
173
) ;
144
174
0 commit comments