@@ -18,7 +18,7 @@ use rustc_middle::ty::query::TyCtxtAt;
1818use rustc_middle:: ty:: subst:: SubstsRef ;
1919use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
2020use 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 } ;
2222
2323use super :: {
2424 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> {
212212
213213/// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
214214/// 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+ }
229234}
230235
231236/// Use the already known layout if given (but sanity check in debug mode),
@@ -241,7 +246,7 @@ pub(super) fn from_known_layout<'tcx>(
241246 if cfg ! ( debug_assertions) {
242247 let check_layout = compute ( ) ?;
243248 assert ! (
244- mir_assign_valid_types( check_layout. ty , known_layout. ty ) ,
249+ mir_assign_valid_types( check_layout, known_layout) ,
245250 "expected type differs from actual type.\n expected: {:?}\n actual: {:?}" ,
246251 known_layout. ty,
247252 check_layout. ty,
0 commit comments