Skip to content

Commit 4eb5fcb

Browse files
committed
Compute the layout of uninhabited structs
1 parent 22bc9e1 commit 4eb5fcb

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,6 @@ pub enum UnsupportedOpInfo<'tcx> {
389389
/// Free-form case. Only for errors that are never caught!
390390
Unsupported(String),
391391

392-
/// FIXME(#64506) Error used to work around accessing projections of
393-
/// uninhabited types.
394-
UninhabitedValue,
395-
396392
// -- Everything below is not categorized yet --
397393
FunctionAbiMismatch(Abi, Abi),
398394
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -556,8 +552,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
556552
not a power of two"),
557553
Unsupported(ref msg) =>
558554
write!(f, "{}", msg),
559-
UninhabitedValue =>
560-
write!(f, "tried to use an uninhabited value"),
561555
}
562556
}
563557
}

src/librustc/ty/layout.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -825,10 +825,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
825825
});
826826
(present_variants.next(), present_variants.next())
827827
};
828-
if present_first.is_none() {
829-
// Uninhabited because it has no variants, or only absent ones.
830-
return tcx.layout_raw(param_env.and(tcx.types.never));
831-
}
828+
let present_first = if present_first.is_none() {
829+
if def.is_enum() {
830+
// Uninhabited because it has no variants, or only absent ones.
831+
return tcx.layout_raw(param_env.and(tcx.types.never));
832+
} else {
833+
// if it's a struct, still compute a layout so that we can still compute the
834+
// field offsets
835+
Some(VariantIdx::new(0))
836+
}
837+
} else {
838+
present_first
839+
};
832840

833841
let is_struct = !def.is_enum() ||
834842
// Only one variant is present.

src/librustc_mir/interpret/place.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc::mir;
99
use rustc::mir::interpret::truncate;
1010
use rustc::ty::{self, Ty};
1111
use rustc::ty::layout::{
12-
self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
12+
self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
1313
};
1414
use rustc::ty::TypeFoldable;
1515

@@ -377,20 +377,17 @@ where
377377
layout::FieldPlacement::Array { stride, .. } => {
378378
let len = base.len(self)?;
379379
if field >= len {
380-
// This can be violated because this runs during promotion on code where the
381-
// type system has not yet ensured that such things don't happen.
380+
// This can be violated because the index (field) can be a runtime value
381+
// provided by the user.
382382
debug!("tried to access element {} of array/slice with length {}", field, len);
383383
throw_panic!(BoundsCheck { len, index: field });
384384
}
385385
stride * field
386386
}
387387
layout::FieldPlacement::Union(count) => {
388-
// FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved
389-
if base.layout.abi == Abi::Uninhabited {
390-
throw_unsup!(UninhabitedValue);
391-
}
392388
assert!(field < count as u64,
393-
"Tried to access field {} of union with {} fields", field, count);
389+
"Tried to access field {} of union {:#?} with {} fields",
390+
field, base.layout, count);
394391
// Offset is always 0
395392
Size::from_bytes(0)
396393
}

src/test/ui/issues/issue-64506.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
3+
#[derive(Copy, Clone)]
4+
pub struct ChildStdin {
5+
inner: AnonPipe,
6+
}
7+
8+
#[derive(Copy, Clone)]
9+
enum AnonPipe {}
10+
11+
const FOO: () = {
12+
union Foo {
13+
a: ChildStdin,
14+
b: (),
15+
}
16+
let x = unsafe { Foo { b: () }.a };
17+
let x = &x.inner;
18+
};
19+
20+
fn main() {}

0 commit comments

Comments
 (0)