Skip to content

Commit 9978521

Browse files
committed
safe transmute: support Single enums
Fixes rust-lang#125811
1 parent 1d43fbb commit 9978521

File tree

4 files changed

+40
-59
lines changed

4 files changed

+40
-59
lines changed

compiler/rustc_const_eval/src/interpret/discriminant.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
241241
variant_index: VariantIdx,
242242
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
243243
match self.layout_of(ty)?.variants {
244-
abi::Variants::Single { index } => {
245-
assert_eq!(index, variant_index);
246-
Ok(None)
247-
}
244+
abi::Variants::Single { .. } => Ok(None),
248245

249246
abi::Variants::Multiple {
250247
tag_encoding: TagEncoding::Direct,

compiler/rustc_transmute/src/layout/tree.rs

+23-21
Original file line numberDiff line numberDiff line change
@@ -331,30 +331,32 @@ pub(crate) mod rustc {
331331
assert!(def.is_enum());
332332
let layout = ty_and_layout.layout;
333333

334-
if let Variants::Multiple { tag_field, .. } = layout.variants() {
335-
// For enums (but not coroutines), the tag field is
336-
// currently always the first field of the layout.
337-
assert_eq!(*tag_field, 0);
338-
}
334+
// Computes the variant of a given index.
335+
let layout_of_variant = |index| {
336+
let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index));
337+
let variant_def = Def::Variant(def.variant(index));
338+
let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index);
339+
Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx)
340+
};
339341

340-
let variants = def.discriminants(cx.tcx()).try_fold(
341-
Self::uninhabited(),
342-
|variants, (idx, ref discriminant)| {
343-
let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, idx));
344-
let variant_def = Def::Variant(def.variant(idx));
345-
let variant_ty_and_layout = ty_and_layout.for_variant(&cx, idx);
346-
let variant = Self::from_variant(
347-
variant_def,
348-
tag,
349-
variant_ty_and_layout,
350-
layout.size,
351-
cx,
342+
match layout.variants() {
343+
Variants::Single { index } => layout_of_variant(*index),
344+
Variants::Multiple { tag_field, .. } => {
345+
// For enums (but not coroutines), the tag field is
346+
// currently always the first field of the layout.
347+
assert_eq!(*tag_field, 0);
348+
349+
let variants = def.discriminants(cx.tcx()).try_fold(
350+
Self::uninhabited(),
351+
|variants, (idx, ref discriminant)| {
352+
let variant = layout_of_variant(idx)?;
353+
Result::<Self, Err>::Ok(variants.or(variant))
354+
},
352355
)?;
353-
Result::<Self, Err>::Ok(variants.or(variant))
354-
},
355-
)?;
356356

357-
return Ok(Self::def(Def::Adt(def)).then(variants));
357+
return Ok(Self::def(Def::Adt(def)).then(variants));
358+
}
359+
}
358360
}
359361

360362
/// Constructs a `Tree` from a 'variant-like' layout.

tests/crashes/125811.rs

-34
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ check-pass
2+
//! Tests that we do not regress rust-lang/rust#125811
3+
#![feature(transmutability)]
4+
5+
fn assert_transmutable<T: std::mem::BikeshedIntrinsicFrom<Enum>>() {}
6+
7+
enum Uninhabited {}
8+
9+
enum Enum {
10+
X,
11+
Y(Uninhabited)
12+
}
13+
14+
fn main() {
15+
assert_transmutable::<()>();
16+
}

0 commit comments

Comments
 (0)