@@ -283,6 +283,18 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
283283 }
284284}
285285
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+
286298// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
287299impl < ' mir , ' tcx , Tag , M > InterpCx < ' mir , ' tcx , M >
288300where
@@ -869,10 +881,10 @@ where
869881 // We do NOT compare the types for equality, because well-typed code can
870882 // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
871883 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 ,
876888 ) ;
877889
878890 // Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
@@ -923,7 +935,7 @@ where
923935 src : OpTy < ' tcx , M :: PointerTag > ,
924936 dest : PlaceTy < ' tcx , M :: PointerTag > ,
925937 ) -> InterpResult < ' tcx > {
926- if src. layout . layout == dest. layout . layout {
938+ if mir_assign_valid_types ( src. layout . ty , dest. layout . ty ) {
927939 // Fast path: Just use normal `copy_op`
928940 return self . copy_op ( src, dest) ;
929941 }
0 commit comments