Skip to content

Commit 3fbdbcc

Browse files
committed
CastKind::Transmute is only allowed in MirPhase::Runtime
1 parent 2405ac4 commit 3fbdbcc

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2246,7 +2246,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22462246
span_mirbug!(
22472247
self,
22482248
rvalue,
2249-
"Unexpected CastKind::Transmute, should only appear after lowering_intrinsics",
2249+
"Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
22502250
);
22512251
}
22522252
}

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -620,23 +620,41 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
620620
}
621621
}
622622
CastKind::Transmute => {
623-
let src_layout = self.tcx.layout_of(self.param_env.and(op_ty));
624-
let dst_layout = self.tcx.layout_of(self.param_env.and(*target_type));
625-
if let Err(e) = src_layout {
623+
if let MirPhase::Runtime(..) = self.mir_phase {
624+
// `mem::transmute` currently requires types concrete enough
625+
// to *know* that their sizes are the same, and we repeat
626+
// that check here. This restriction may be lifted in future,
627+
// should some optimizations need to it be more general.
628+
// (It might just end up being UB if they don't match, say.)
629+
630+
let src_layout = self.tcx.layout_of(self.param_env.and(op_ty));
631+
let dst_layout = self.tcx.layout_of(self.param_env.and(*target_type));
632+
if let Err(e) = src_layout {
633+
self.fail(
634+
location,
635+
format!(
636+
"Unable to compute layout for source type {op_ty:?}: {e}"
637+
),
638+
);
639+
}
640+
if let Err(e) = dst_layout {
641+
self.fail(location, format!("Unable to compute layout for destination type {target_type:?}: {e}"));
642+
}
643+
644+
if let (Ok(src_layout), Ok(dst_layout)) = (src_layout, dst_layout) {
645+
if src_layout.layout.size() != dst_layout.layout.size() {
646+
self.fail(location, format!("Source and destination layouts have different sizes: {src_layout:?} vs {dst_layout:?}"));
647+
}
648+
}
649+
} else {
626650
self.fail(
627651
location,
628-
format!("Unable to compute layout for source type {op_ty:?}: {e}"),
652+
format!(
653+
"Transmute is not supported in non-runtime phase {:?}.",
654+
self.mir_phase
655+
),
629656
);
630657
}
631-
if let Err(e) = dst_layout {
632-
self.fail(location, format!("Unable to compute layout for destination type {target_type:?}: {e}"));
633-
}
634-
635-
if let (Ok(src_layout), Ok(dst_layout)) = (src_layout, dst_layout) {
636-
if src_layout.layout.size() != dst_layout.layout.size() {
637-
self.fail(location, format!("Source and destination layouts have different sizes: {src_layout:?} vs {dst_layout:?}"));
638-
}
639-
}
640658
}
641659
}
642660
}

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ pub enum MirPhase {
8383
/// access to. This occurs in generator bodies. Such locals do not behave like other locals,
8484
/// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
8585
/// all generator bodies are lowered and so all places that look like locals really are locals.
86+
/// - Intrinsics: In analysis MIR, intrinsics are typically represented as [`TerminatorKind::Call`]s
87+
/// to their `extern "rust-intrinsic"` declarations. In runtime MIR, some intrinsics are lowered
88+
/// to MIR constructs not used earlier, such as `mem::transmute` → [`CastKind::Transmute`].
8689
///
8790
/// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
8891
/// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
@@ -1190,6 +1193,8 @@ pub enum CastKind {
11901193
PtrToPtr,
11911194
FnPtrToPtr,
11921195
/// Reinterpret the bits of the input as a different type.
1196+
///
1197+
/// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`].
11931198
Transmute,
11941199
}
11951200

0 commit comments

Comments
 (0)