@@ -18,7 +18,7 @@ use rustc_middle::ty::query::TyCtxtAt;
18
18
use rustc_middle:: ty:: subst:: SubstsRef ;
19
19
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
20
20
use rustc_span:: source_map:: DUMMY_SP ;
21
- use rustc_target:: abi:: { Align , HasDataLayout , LayoutOf , Size , TargetDataLayout } ;
21
+ use rustc_target:: abi:: { Abi , Align , HasDataLayout , LayoutOf , Size , TargetDataLayout } ;
22
22
23
23
use super :: {
24
24
Immediate , MPlaceTy , Machine , MemPlace , MemPlaceMeta , Memory , OpTy , Operand , Place , PlaceTy ,
@@ -212,20 +212,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
212
212
213
213
/// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
214
214
/// This test should be symmetric, as it is primarily about layout compatibility.
215
- pub ( super ) fn mir_assign_valid_types < ' tcx > ( src : Ty < ' tcx > , dest : Ty < ' tcx > ) -> bool {
216
- src == dest
217
- || match ( & src. kind , & dest. kind ) {
218
- ( ty:: Ref ( _, src_pointee, _) , ty:: Ref ( _, dest_pointee, _) ) => {
219
- // After optimizations, there can be assignments that change reference mutability.
220
- // This does not affect reference layout, so that is fine.
221
- src_pointee == dest_pointee
222
- }
223
- ( ty:: FnPtr ( _) , ty:: FnPtr ( _) ) => {
224
- // All function pointers have equal layout, and thus can be assigned.
225
- true
226
- }
227
- _ => false ,
228
- }
215
+ pub ( super ) fn mir_assign_valid_types < ' tcx > (
216
+ src : TyAndLayout < ' tcx > ,
217
+ dest : TyAndLayout < ' tcx > ,
218
+ ) -> bool {
219
+ if src. ty == dest. ty {
220
+ // Equal types, all is good.
221
+ return true ;
222
+ }
223
+ // Type-changing assignments can happen for (at least) two reasons:
224
+ // - `&mut T` -> `&T` gets optimized from a reborrow to a mere assignment.
225
+ // - Subtyping is used. While all normal lifetimes are erased, higher-ranked lifetime
226
+ // bounds are still around and can lead to type differences.
227
+ // There is no good way to check the latter, so we compare layouts instead -- but only
228
+ // for values with `Scalar`/`ScalarPair` abi.
229
+ // FIXME: Do something more accurate, type-based.
230
+ match & src. abi {
231
+ Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) => src. layout == dest. layout ,
232
+ _ => false ,
233
+ }
229
234
}
230
235
231
236
/// Use the already known layout if given (but sanity check in debug mode),
@@ -241,7 +246,7 @@ pub(super) fn from_known_layout<'tcx>(
241
246
if cfg ! ( debug_assertions) {
242
247
let check_layout = compute ( ) ?;
243
248
assert ! (
244
- mir_assign_valid_types( check_layout. ty , known_layout. ty ) ,
249
+ mir_assign_valid_types( check_layout, known_layout) ,
245
250
"expected type differs from actual type.\n expected: {:?}\n actual: {:?}" ,
246
251
known_layout. ty,
247
252
check_layout. ty,
0 commit comments