mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +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,
|
present_first @ Some(_) => present_first,
|
||||||
// Uninhabited because it has no variants, or only absent ones.
|
// 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)),
|
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
|
// If it's a struct, still compute a layout so that we can still compute the
|
||||||
// field offsets
|
// field offsets.
|
||||||
None => Some(VariantIdx::new(0)),
|
None => Some(VariantIdx::new(0)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1990,7 +1990,15 @@ where
|
|||||||
{
|
{
|
||||||
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
|
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
|
||||||
let details = match this.variants {
|
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 } => {
|
Variants::Single { index } => {
|
||||||
// Deny calling for_variant more than once for non-Single enums.
|
// 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>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
let base = match op.try_as_mplace(self) {
|
let base = match op.try_as_mplace(self) {
|
||||||
Ok(mplace) => {
|
Ok(mplace) => {
|
||||||
// The easy case
|
// We can reuse the mplace field computation logic for indirect operands
|
||||||
let field = self.mplace_field(mplace, field)?;
|
let field = self.mplace_field(mplace, field)?;
|
||||||
return Ok(field.into());
|
return Ok(field.into());
|
||||||
}
|
}
|
||||||
|
@ -410,14 +410,6 @@ where
|
|||||||
stride * field
|
stride * field
|
||||||
}
|
}
|
||||||
layout::FieldPlacement::Union(count) => {
|
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!(
|
assert!(
|
||||||
field < count as u64,
|
field < count as u64,
|
||||||
"Tried to access field {} of union {:#?} with {} fields",
|
"Tried to access field {} of union {:#?} with {} fields",
|
||||||
|
@ -660,7 +660,11 @@ impl FieldPlacement {
|
|||||||
|
|
||||||
pub fn offset(&self, i: usize) -> Size {
|
pub fn offset(&self, i: usize) -> Size {
|
||||||
match *self {
|
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 } => {
|
FieldPlacement::Array { stride, count } => {
|
||||||
let i = i as u64;
|
let i = i as u64;
|
||||||
assert!(i < count);
|
assert!(i < count);
|
||||||
|
Loading…
Reference in New Issue
Block a user