mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Compute the correct layout for variants of uninhabited enums and readd a long lost assertion
This reverts part of commit 9712fa4059
.
This commit is contained in:
parent
303d8aff60
commit
cdc730457e
@ -782,8 +782,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
present_first @ Some(_) => present_first,
|
||||
// Uninhabited because it has no variants, or only absent ones.
|
||||
None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)),
|
||||
// if it's a struct, still compute a layout so that we can still compute the
|
||||
// field offsets
|
||||
// If it's a struct, still compute a layout so that we can still compute the
|
||||
// field offsets.
|
||||
None => Some(VariantIdx::new(0)),
|
||||
};
|
||||
|
||||
@ -1990,7 +1990,15 @@ where
|
||||
{
|
||||
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
|
||||
let details = match this.variants {
|
||||
Variants::Single { index } if index == variant_index => this.details,
|
||||
Variants::Single { index }
|
||||
// If all variants but one are uninhabited, the variant layout is the enum layout.
|
||||
if index == variant_index &&
|
||||
// Don't confuse variants of uninhabited enums with the enum itself.
|
||||
// For more details see https://github.com/rust-lang/rust/issues/69763.
|
||||
this.fields != FieldPlacement::Union(0) =>
|
||||
{
|
||||
this.details
|
||||
}
|
||||
|
||||
Variants::Single { index } => {
|
||||
// Deny calling for_variant more than once for non-Single enums.
|
||||
|
@ -356,7 +356,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
let base = match op.try_as_mplace(self) {
|
||||
Ok(mplace) => {
|
||||
// The easy case
|
||||
// We can reuse the mplace field computation logic for indirect operands
|
||||
let field = self.mplace_field(mplace, field)?;
|
||||
return Ok(field.into());
|
||||
}
|
||||
|
@ -410,14 +410,6 @@ where
|
||||
stride * field
|
||||
}
|
||||
layout::FieldPlacement::Union(count) => {
|
||||
// This is a narrow bug-fix for rust-lang/rust#69191: if we are
|
||||
// trying to access absent field of uninhabited variant, then
|
||||
// signal UB (but don't ICE the compiler).
|
||||
// FIXME temporary hack to work around incoherence between
|
||||
// layout computation and MIR building
|
||||
if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited {
|
||||
throw_ub!(Unreachable);
|
||||
}
|
||||
assert!(
|
||||
field < count as u64,
|
||||
"Tried to access field {} of union {:#?} with {} fields",
|
||||
|
@ -660,7 +660,11 @@ impl FieldPlacement {
|
||||
|
||||
pub fn offset(&self, i: usize) -> Size {
|
||||
match *self {
|
||||
FieldPlacement::Union(_) => Size::ZERO,
|
||||
FieldPlacement::Union(count) => {
|
||||
assert!(i < count,
|
||||
"Tried to access field {} of union with {} fields", i, count);
|
||||
Size::ZERO
|
||||
},
|
||||
FieldPlacement::Array { stride, count } => {
|
||||
let i = i as u64;
|
||||
assert!(i < count);
|
||||
|
Loading…
Reference in New Issue
Block a user