]> git.lizzy.rs Git - rust.git/commitdiff
Miri engine: stronger type-based sanity check for assignments
authorRalf Jung <post@ralfj.de>
Sun, 29 Mar 2020 12:10:16 +0000 (14:10 +0200)
committerRalf Jung <post@ralfj.de>
Thu, 2 Apr 2020 20:33:47 +0000 (22:33 +0200)
src/librustc_mir/interpret/place.rs

index ece54daf4c61df876484fdc4f051778f1ae0f6ce..b16c7ffbffd9f0335160279cae14f00571fefd24 100644 (file)
@@ -283,6 +283,18 @@ pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
     }
 }
 
+/// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
+fn mir_assign_valid_types<'tcx>(src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
+    src == dest
+        || match (&src.kind, &dest.kind) {
+            // After MIR optimizations, there can be assignments that change reference mutability.
+            (ty::Ref(_, src_pointee, _), ty::Ref(_, dest_pointee, _)) => {
+                src_pointee == dest_pointee
+            }
+            _ => false,
+        }
+}
+
 // separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
 impl<'mir, 'tcx, Tag, M> InterpCx<'mir, 'tcx, M>
 where
@@ -869,10 +881,10 @@ fn copy_op_no_validate(
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
         assert!(
-            src.layout.layout == dest.layout.layout,
-            "Layout mismatch when copying!\nsrc: {:#?}\ndest: {:#?}",
-            src,
-            dest
+            mir_assign_valid_types(src.layout.ty, dest.layout.ty),
+            "type mismatch when copying!\nsrc: {:?}, dest: {:?}",
+            src.layout.ty,
+            dest.layout.ty,
         );
 
         // Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
@@ -923,7 +935,7 @@ pub fn copy_op_transmute(
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        if src.layout.layout == dest.layout.layout {
+        if mir_assign_valid_types(src.layout.ty, dest.layout.ty) {
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }