diff options
| author | bors <bors@rust-lang.org> | 2019-10-14 15:52:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-10-14 15:52:51 +0000 |
| commit | e413dc36a83a5aad3ab6270373000693a917e92b (patch) | |
| tree | 3f47bc5fe61faf2c50a843073147636bfda57893 | |
| parent | 446e5e57b667c841ba3ebb4b41b44fb98bd3af4b (diff) | |
| parent | 373c362b7ed0df2dfbc21853e53d5082f20d3de8 (diff) | |
| download | rust-e413dc36a83a5aad3ab6270373000693a917e92b.tar.gz rust-e413dc36a83a5aad3ab6270373000693a917e92b.zip | |
Auto merge of #64987 - oli-obk:code_reuse_prevents_bugs, r=eddyb
Compute the layout of uninhabited structs fixes #64506 r? @eddyb
| -rw-r--r-- | src/librustc/mir/interpret/error.rs | 6 | ||||
| -rw-r--r-- | src/librustc/ty/layout.rs | 10 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/place.rs | 13 | ||||
| -rw-r--r-- | src/librustc_target/abi/mod.rs | 6 | ||||
| -rw-r--r-- | src/test/ui/consts/issue-64506.rs | 20 |
5 files changed, 37 insertions, 18 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 71967b513a0..ac99ccd45ea 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -389,10 +389,6 @@ pub enum UnsupportedOpInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// FIXME(#64506) Error used to work around accessing projections of - /// uninhabited types. - UninhabitedValue, - // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), @@ -556,8 +552,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { not a power of two"), Unsupported(ref msg) => write!(f, "{}", msg), - UninhabitedValue => - write!(f, "tried to use an uninhabited value"), } } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index ce7e1822d9a..aed9e87a168 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -824,10 +824,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }); (present_variants.next(), present_variants.next()) }; - if present_first.is_none() { + let present_first = match present_first { + present_first @ Some(_) => present_first, // Uninhabited because it has no variants, or only absent ones. - 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 + // field offsets + None => Some(VariantIdx::new(0)), + }; let is_struct = !def.is_enum() || // Only one variant is present. diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 3ba989529f1..903eb3c1c44 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,7 +9,7 @@ use rustc::mir; use rustc::mir::interpret::truncate; use rustc::ty::{self, Ty}; use rustc::ty::layout::{ - self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt + self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt }; use rustc::ty::TypeFoldable; @@ -377,20 +377,17 @@ where layout::FieldPlacement::Array { stride, .. } => { let len = base.len(self)?; if field >= len { - // This can be violated because this runs during promotion on code where the - // type system has not yet ensured that such things don't happen. + // This can be violated because the index (field) can be a runtime value + // provided by the user. debug!("tried to access element {} of array/slice with length {}", field, len); throw_panic!(BoundsCheck { len, index: field }); } stride * field } layout::FieldPlacement::Union(count) => { - // FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved - if base.layout.abi == Abi::Uninhabited { - throw_unsup!(UninhabitedValue); - } assert!(field < count as u64, - "Tried to access field {} of union with {} fields", field, count); + "Tried to access field {} of union {:#?} with {} fields", + field, base.layout, count); // Offset is always 0 Size::from_bytes(0) } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 26d37f196be..fde5c5bed4d 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -738,7 +738,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); diff --git a/src/test/ui/consts/issue-64506.rs b/src/test/ui/consts/issue-64506.rs new file mode 100644 index 00000000000..db3e85a7bdf --- /dev/null +++ b/src/test/ui/consts/issue-64506.rs @@ -0,0 +1,20 @@ +// check-pass + +#[derive(Copy, Clone)] +pub struct ChildStdin { + inner: AnonPipe, +} + +#[derive(Copy, Clone)] +enum AnonPipe {} + +const FOO: () = { + union Foo { + a: ChildStdin, + b: (), + } + let x = unsafe { Foo { b: () }.a }; + let x = &x.inner; +}; + +fn main() {} |
