@@ -283,6 +283,18 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
283
283
}
284
284
}
285
285
286
+ /// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
287
+ fn mir_assign_valid_types < ' tcx > ( src : Ty < ' tcx > , dest : Ty < ' tcx > ) -> bool {
288
+ src == dest
289
+ || match ( & src. kind , & dest. kind ) {
290
+ // After MIR optimizations, there can be assignments that change reference mutability.
291
+ ( ty:: Ref ( _, src_pointee, _) , ty:: Ref ( _, dest_pointee, _) ) => {
292
+ src_pointee == dest_pointee
293
+ }
294
+ _ => false ,
295
+ }
296
+ }
297
+
286
298
// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
287
299
impl < ' mir , ' tcx , Tag , M > InterpCx < ' mir , ' tcx , M >
288
300
where
@@ -869,10 +881,10 @@ where
869
881
// We do NOT compare the types for equality, because well-typed code can
870
882
// actually "transmute" `&mut T` to `&T` in an assignment without a cast.
871
883
assert ! (
872
- src. layout. layout == dest. layout. layout ,
873
- "Layout mismatch when copying!\n src: {:#?} \n dest : {:# ?}" ,
874
- src,
875
- dest
884
+ mir_assign_valid_types ( src. layout. ty , dest. layout. ty ) ,
885
+ "type mismatch when copying!\n src: {:?}, dest : {:?}" ,
886
+ src. layout . ty ,
887
+ dest. layout . ty ,
876
888
) ;
877
889
878
890
// Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
@@ -923,7 +935,7 @@ where
923
935
src : OpTy < ' tcx , M :: PointerTag > ,
924
936
dest : PlaceTy < ' tcx , M :: PointerTag > ,
925
937
) -> InterpResult < ' tcx > {
926
- if src. layout . layout == dest. layout . layout {
938
+ if mir_assign_valid_types ( src. layout . ty , dest. layout . ty ) {
927
939
// Fast path: Just use normal `copy_op`
928
940
return self . copy_op ( src, dest) ;
929
941
}
0 commit comments