From cbf52b16758dd17fd60b5b73feb803d1ffc1654b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 10:13:11 +0100 Subject: [PATCH 01/17] remove non-sysroot sources from rust-src component --- src/bootstrap/dist.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 76478abd0de..8215211ea1c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1002,8 +1002,6 @@ impl Step for Src { "src/tools/rustc-std-workspace-core", "src/tools/rustc-std-workspace-alloc", "src/tools/rustc-std-workspace-std", - "src/librustc", - "src/librustc_ast", ]; copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src); From a9259fb7c7f9f6138b6b774679295084f18a24a3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 2 Mar 2020 19:28:18 -0500 Subject: [PATCH 02/17] Try to ensure usize marker does not get merged --- src/libcore/fmt/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 993b1073493..a9dd098ab0f 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -264,8 +264,18 @@ pub struct ArgumentV1<'a> { // could have been miscompiled. In practice, we never call as_usize on non-usize // containing data (as a matter of static generation of the formatting // arguments), so this is merely an additional check. +// +// We primarily want to ensure that the function pointer at `USIZE_MARKER` has +// an address corresponding *only* to functions that also take `&usize` as their +// first argument. The read_volatile here ensures that we can safely ready out a +// usize from the passed reference and that this address does not point at a +// non-usize taking function. #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {}; +static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| { + // SAFETY: ptr is a reference + let _v: usize = unsafe { crate::ptr::read_volatile(ptr) }; + loop {} +}; impl<'a> ArgumentV1<'a> { #[doc(hidden)] From 9384cba72e09790eaf166510bed885ff1771dbfe Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 3 Mar 2020 09:41:44 +0100 Subject: [PATCH 03/17] Documentation and slight simplification of BTreeMap's internals --- src/liballoc/collections/btree/node.rs | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index c1bd68a020a..c75c12df2d0 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -153,10 +153,15 @@ impl InternalNode { } } -/// An owned pointer to a node. This basically is either `Box>` or -/// `Box>`. However, it contains no information as to which of the two types -/// of nodes is actually behind the box, and, partially due to this lack of information, has no -/// destructor. +/// A managed, non-null pointer to a node. This is either an owned pointer to +/// `LeafNode`, an owned pointer to `InternalNode`, or a (not owned) +/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE). +/// All of these types have a `NodeHeader` prefix, meaning that they have at +/// least the same size as `NodeHeader` and store the same kinds of data at the same +/// offsets; and they have a pointer alignment at least as large as `NodeHeader`'s. +/// However, `BoxedNode` contains no information as to which of the three types +/// of nodes it actually contains, and, partially due to this lack of information, +/// has no destructor. struct BoxedNode { ptr: Unique>, } @@ -167,9 +172,7 @@ impl BoxedNode { } fn from_internal(node: Box>) -> Self { - unsafe { - BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode) } - } + BoxedNode { ptr: Box::into_unique(node).cast() } } unsafe fn from_ptr(ptr: NonNull>) -> Self { @@ -181,10 +184,11 @@ impl BoxedNode { } } -/// An owned tree. Note that despite being owned, this does not have a destructor, -/// and must be cleaned up manually. +/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor, +/// and must be cleaned up manually if it is an owned tree. pub struct Root { node: BoxedNode, + /// The number of levels below the root node. height: usize, } @@ -192,21 +196,21 @@ unsafe impl Sync for Root {} unsafe impl Send for Root {} impl Root { + /// Whether the instance of `Root` wraps a shared, empty root node. If not, + /// the entire tree is uniquely owned by the owner of the `Root` instance. pub fn is_shared_root(&self) -> bool { self.as_ref().is_shared_root() } + /// Returns a shared tree, wrapping a shared root node that is eternally empty. pub fn shared_empty_root() -> Self { Root { - node: unsafe { - BoxedNode::from_ptr(NonNull::new_unchecked( - &EMPTY_ROOT_NODE as *const _ as *const LeafNode as *mut _, - )) - }, + node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) }, height: 0, } } + /// Returns a new owned tree, with its own root node that is initially empty. pub fn new_leaf() -> Self { Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } } @@ -310,6 +314,7 @@ impl Root { /// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior. /// Turning this into a `NodeHeader` reference is always safe. pub struct NodeRef { + /// The number of levels below the node. height: usize, node: NonNull>, // `root` is null unless the borrow type is `Mut` From 13d5ee1c4f36cc05e87b23657fa934fe2d02f73c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Mar 2020 12:52:16 +0100 Subject: [PATCH 04/17] Cleanup E0390 explanation --- src/librustc_error_codes/error_codes/E0390.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0390.md b/src/librustc_error_codes/error_codes/E0390.md index 9d05740d6f5..ecc5b5568ad 100644 --- a/src/librustc_error_codes/error_codes/E0390.md +++ b/src/librustc_error_codes/error_codes/E0390.md @@ -1,4 +1,6 @@ -You tried to implement methods for a primitive type. Erroneous code example: +A method was implemented on a primitive type. + +Erroneous code example: ```compile_fail,E0390 struct Foo { From 31183bbd5a0d4e7873f0c789dc537b1eab60dee1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 6 Mar 2020 14:27:09 +0000 Subject: [PATCH 05/17] Fix missing ` in doc for File::with_options --- src/libstd/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 09be3f13050..e20fcfafa22 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -407,7 +407,7 @@ impl File { /// /// It is equivalent to `OpenOptions::new()` but allows you to write more /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` - /// you can write `File::with_options().read(true).open("foo.txt"). This + /// you can write `File::with_options().read(true).open("foo.txt")`. This /// also avoids the need to import `OpenOptions`. /// /// See the [`OpenOptions::new`] function for more details. From 6548be2ba95c29cfd0f3324f4b314a64853b2f57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 11:45:02 +0100 Subject: [PATCH 06/17] 'fieldless enums' is not what I meant -- it's empty/uninhabited enums, really --- src/librustc_mir/interpret/validity.rs | 3 +-- src/librustc_target/abi/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 731dcc6a25f..8989da9a91a 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -579,13 +579,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } // Check primitive types. We do this after checking for uninhabited types, - // to exclude fieldless enums (that also appear as fieldless unions here). + // to exclude uninhabited enums (that also appear as fieldless unions here). // Primitives can have varying layout, so we check them separately and before aggregate // handling. // It is CRITICAL that we get this check right, or we might be validating the wrong thing! let primitive = match op.layout.fields { // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - // (Fieldless enums also appear here, but they are uninhabited and thus handled above.) layout::FieldPlacement::Union(0) => true, _ => op.layout.ty.builtin_deref(true).is_some(), }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index ffef38cedfc..316e07425c5 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -872,7 +872,7 @@ impl Niche { #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct LayoutDetails { /// Says where the fields are located within the layout. - /// Primitives and fieldless enums appear as unions without fields. + /// Primitives and uninhabited enums appear as unions without fields. pub fields: FieldPlacement, /// Encodes information about multi-variant layouts. From d47196b2ec23a26c03b1546449f29300d42a4840 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 13:09:13 +0100 Subject: [PATCH 07/17] miri value visitor: detect primitives by type, not layout --- src/librustc_mir/interpret/validity.rs | 284 ++++++++++-------- .../ui/consts/const-eval/ub-uninhabit.stderr | 2 +- .../validate_uninhabited_zsts.stderr | 2 +- .../ui/consts/validate_never_arrays.stderr | 6 +- 4 files changed, 163 insertions(+), 131 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 8989da9a91a..defb490199b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -306,23 +306,119 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(()) } - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + /// Check a reference or `Box`. + fn check_safe_pointer(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; + // Handle wide pointers. + // Check metadata early, for better diagnostics + let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + if place.layout.is_unsized() { + self.check_wide_ptr_meta(place.meta, place.layout)?; + } + // Make sure this is dereferenceable and all. + let (size, align) = self + .ecx + .size_and_align_of(place.meta, place.layout)? + // for the purpose of validity, consider foreign types to have + // alignment and size determined by the layout (size will be 0, + // alignment should take attributes into account). + .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); + let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( + place.ptr, + size, + Some(align), + CheckInAllocMsg::InboundsTest, + ) { + Ok(ptr) => ptr, + Err(err) => { + info!( + "{:?} did not pass access check for size {:?}, align {:?}", + place.ptr, size, align + ); + match err.kind { + err_unsup!(InvalidNullPointerUsage) => { + throw_validation_failure!("a NULL reference", self.path) + } + err_unsup!(AlignmentCheckFailed { required, has }) => { + throw_validation_failure!( + format_args!( + "an unaligned reference \ + (required {} byte alignment but found {})", + required.bytes(), + has.bytes() + ), + self.path + ) + } + err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( + "a dangling reference (created from integer)", + self.path + ), + _ => throw_validation_failure!( + "a dangling reference (not entirely in bounds)", + self.path + ), + } + } + }; + // Recursive checking + if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { + if let Some(ptr) = ptr { + // not a ZST + // Skip validation entirely for some external statics + let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); + if let Some(GlobalAlloc::Static(did)) = alloc_kind { + // `extern static` cannot be validated as they have no body. + // FIXME: Statics from other crates are also skipped. + // They might be checked at a different type, but for now we + // want to avoid recursing too deeply. This is not sound! + if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { + return Ok(()); + } + } + } + // Proceed recursively even for ZST, no reason to skip them! + // `!` is a ZST and we want to validate it. + // Normalize before handing `place` to tracking because that will + // check for duplicates. + let place = if size.bytes() > 0 { + self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") + } else { + place + }; + let path = &self.path; + ref_tracking.track(place, || { + // We need to clone the path anyway, make sure it gets created + // with enough space for the additional `Deref`. + let mut new_path = Vec::with_capacity(path.len() + 1); + new_path.clone_from(path); + new_path.push(PathElem::Deref); + new_path + }); + } + Ok(()) + } + + /// Check if this is a value of primitive type, and if yes check the validity of the value + /// at that type. Return `true` if the type is indeed primitive. + fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { ty::Bool => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_bool(), value, self.path, "a boolean"); + Ok(true) } ty::Char => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint"); + Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { + let value = self.ecx.read_scalar(value)?; // NOTE: Keep this in sync with the array optimization for int/float // types below! - let value = value.to_scalar_or_undef(); if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous let is_bits = value.not_undef().map_or(false, |v| v.is_bits()); @@ -337,108 +433,32 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. } + Ok(true) } ty::RawPtr(..) => { // We are conservative with undef for integers, but try to // actually enforce our current rules for raw pointers. - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + let place = try_validation!( + self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), + "undefined pointer", + self.path + ); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; } + Ok(true) } - _ if ty.is_box() || ty.is_region_ptr() => { - // Handle wide pointers. - // Check metadata early, for better diagnostics - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); - if place.layout.is_unsized() { - self.check_wide_ptr_meta(place.meta, place.layout)?; - } - // Make sure this is dereferenceable and all. - let (size, align) = self - .ecx - .size_and_align_of(place.meta, place.layout)? - // for the purpose of validity, consider foreign types to have - // alignment and size determined by the layout (size will be 0, - // alignment should take attributes into account). - .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( - place.ptr, - size, - Some(align), - CheckInAllocMsg::InboundsTest, - ) { - Ok(ptr) => ptr, - Err(err) => { - info!( - "{:?} did not pass access check for size {:?}, align {:?}", - place.ptr, size, align - ); - match err.kind { - err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("a NULL reference", self.path) - } - err_unsup!(AlignmentCheckFailed { required, has }) => { - throw_validation_failure!( - format_args!( - "an unaligned reference \ - (required {} byte alignment but found {})", - required.bytes(), - has.bytes() - ), - self.path - ) - } - err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "a dangling reference (created from integer)", - self.path - ), - _ => throw_validation_failure!( - "a dangling reference (not entirely in bounds)", - self.path - ), - } - } - }; - // Recursive checking - if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { - if let Some(ptr) = ptr { - // not a ZST - // Skip validation entirely for some external statics - let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(GlobalAlloc::Static(did)) = alloc_kind { - // `extern static` cannot be validated as they have no body. - // FIXME: Statics from other crates are also skipped. - // They might be checked at a different type, but for now we - // want to avoid recursing too deeply. This is not sound! - if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { - return Ok(()); - } - } - } - // Proceed recursively even for ZST, no reason to skip them! - // `!` is a ZST and we want to validate it. - // Normalize before handing `place` to tracking because that will - // check for duplicates. - let place = if size.bytes() > 0 { - self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") - } else { - place - }; - let path = &self.path; - ref_tracking.track(place, || { - // We need to clone the path anyway, make sure it gets created - // with enough space for the additional `Deref`. - let mut new_path = Vec::with_capacity(path.len() + 1); - new_path.clone_from(path); - new_path.push(PathElem::Deref); - new_path - }); - } + ty::Ref(..) => { + self.check_safe_pointer(value)?; + Ok(true) + } + ty::Adt(def, ..) if def.is_box() => { + // FIXME make sure we have a test for `Box`! + self.check_safe_pointer(value)?; + Ok(true) } ty::FnPtr(_sig) => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; let _fn = try_validation!( value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)), value, @@ -446,11 +466,35 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M "a function pointer" ); // FIXME: Check if the signature matches + Ok(true) } - // This should be all the (inhabited) primitive types - _ => bug!("Unexpected primitive type {}", value.layout.ty), + ty::Never => throw_validation_failure!("a value of the never type `!`", self.path), + ty::Foreign(..) | ty::FnDef(..) => { + // Nothing to check. + Ok(true) + } + // This should be all the (inhabited) primitive types. The rest is compound, we + // check them by visiting their fields/variants. + // (`Str` UTF-8 check happens in `visit_aggregate`, too.) + ty::Adt(..) + | ty::Tuple(..) + | ty::Array(..) + | ty::Slice(..) + | ty::Str + | ty::Dynamic(..) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) => Ok(false), + // Some types only occur during inference, we should not see them here. + ty::Error + | ty::Infer(..) + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Param(..) + | ty::Opaque(..) + | ty::UnnormalizedProjection(..) + | ty::Projection(..) => bug!("Encountered invalid type {:?}", ty), } - Ok(()) } fn visit_scalar( @@ -558,11 +602,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline(always)] - fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> { - // Empty unions are not accepted by rustc. That's great, it means we can - // use that as a signal for detecting primitives. Make sure - // we did not miss any primitive. - assert!(fields > 0); + fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> { + // Empty unions are not accepted by rustc. But uninhabited enums + // claim to be unions, so allow them, too. + assert!(op.layout.abi.is_uninhabited() || fields > 0); Ok(()) } @@ -570,28 +613,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); - if op.layout.abi.is_uninhabited() { - // Uninhabited types do not have sensible layout, stop right here. - throw_validation_failure!( - format_args!("a value of uninhabited type {:?}", op.layout.ty), - self.path - ) - } - - // Check primitive types. We do this after checking for uninhabited types, - // to exclude uninhabited enums (that also appear as fieldless unions here). - // Primitives can have varying layout, so we check them separately and before aggregate - // handling. - // It is CRITICAL that we get this check right, or we might be validating the wrong thing! - let primitive = match op.layout.fields { - // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - layout::FieldPlacement::Union(0) => true, - _ => op.layout.ty.builtin_deref(true).is_some(), - }; - if primitive { - // No need to recurse further or check scalar layout, this is a leaf type. - return self.visit_primitive(op); + // Check primitive types -- the leafs of our recursive descend. + if self.visit_primitive(op)? { + return Ok(()); } + // Sanity check: `builtin_deref` does not know any pointers that are not primitive. + assert!(op.layout.ty.builtin_deref(true).is_none()); // Recursively walk the type. Translate some possible errors to something nicer. match self.walk_value(op) { @@ -618,7 +645,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). match op.layout.abi { - layout::Abi::Uninhabited => unreachable!(), // checked above + layout::Abi::Uninhabited => { + throw_validation_failure!( + format_args!("a value of uninhabited type {:?}", op.layout.ty), + self.path + ); + } layout::Abi::Scalar(ref scalar_layout) => { self.visit_scalar(op, scalar_layout)?; } diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 4fef9aa84ea..350d8353fef 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Bar; 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr index 2a338e27640..d0e35615dab 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Empty; 3] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 203620a771b..77f0a2ebd40 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:3:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:6:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From aa1435b0aef77e0eeb8604fd0eed578772ff7e27 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 20:37:33 +0100 Subject: [PATCH 08/17] const validation ub tests: use transmute instead of unions --- src/test/ui/consts/const-eval/ub-enum.rs | 49 ++-- src/test/ui/consts/const-eval/ub-enum.stderr | 80 +++--- src/test/ui/consts/const-eval/ub-nonnull.rs | 6 +- .../ui/consts/const-eval/ub-nonnull.stderr | 4 +- src/test/ui/consts/const-eval/ub-uninhabit.rs | 10 +- .../ui/consts/const-eval/ub-uninhabit.stderr | 8 +- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 129 +++------- .../ui/consts/const-eval/ub-wide-ptr.stderr | 232 +++++++++--------- 8 files changed, 231 insertions(+), 287 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 483285aa4e1..4e7c7be4a76 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,5 +1,7 @@ +#![feature(const_transmute)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; #[repr(transparent)] #[derive(Copy, Clone)] @@ -10,23 +12,16 @@ struct Wrap(T); enum Enum { A = 0, } -#[repr(C)] -union TransmuteEnum { - in1: &'static u8, - in2: usize, - out1: Enum, - out2: Wrap, -} -const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 }; +const GOOD_ENUM: Enum = unsafe { mem::transmute(0usize) }; -const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; +const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; +const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior -const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; +const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior // (Potentially) invalid enum discriminant @@ -36,39 +31,31 @@ enum Enum2 { A = 2, } -#[repr(C)] -union TransmuteEnum2 { - in1: usize, - in2: &'static u8, - in3: (), - out1: Enum2, - out2: Wrap, // something wrapping the enum so that we test layout first, not enum - out3: Option, -} -const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; +const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; +const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; +// something wrapping the enum so that we test layout first, not enum +const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior // Undef enum discriminant. -const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} +const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR is undefined behavior // Pointer value in an enum with a niche that is not just 0. -const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; +const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). -#[repr(C)] -union TransmuteChar { - a: u32, - b: char, -} // Need to create something which does not clash with enum layout optimizations. -const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); +const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior fn main() { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8c47d68e968..95d4155be91 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,72 +1,72 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:23:1 + --> $DIR/ub-enum.rs:18:1 | -LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:26:1 + --> $DIR/ub-enum.rs:21:1 | -LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:24:1 | -LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:34:1 + | +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:36:1 + | +LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:39:1 + | +LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:48:1 | -LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:50:1 - | -LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:52:1 | -LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:56:1 + --> $DIR/ub-enum.rs:58:1 | -LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:60:1 - | -LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:71:1 - | -LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 8ce64ced7df..1f46b6c98ad 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -25,11 +25,11 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value #[repr(C)] -union Transmute { +union MaybeUninit { uninit: (), - out: NonZeroU8, + init: T, } -const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; +const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value // Also test other uses of rustc_layout_scalar_valid_range_start diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index ec056187057..edfc7ac837f 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:32:1 | -LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes +LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index d2745d71bdb..e7350ae2716 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -7,18 +7,18 @@ use std::mem; enum Bar {} #[repr(C)] -union TransmuteUnion { - a: A, - b: B, +union MaybeUninit { + uninit: (), + init: T, } -const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; +const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR it is undefined behavior to use this value -const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 350d8353fef..8ce4279a8b7 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | -LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar +LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -17,8 +17,8 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | -LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index a5c2a57c6c8..ada82fc83a8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,72 +1,18 @@ // ignore-tidy-linelength +#![feature(const_transmute)] #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; + // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" #[repr(C)] -union BoolTransmute { - val: u8, - bl: bool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct SliceRepr { - ptr: *const u8, - len: usize, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadSliceRepr { - ptr: *const u8, - len: &'static u8, -} - -#[repr(C)] -union SliceTransmute { - repr: SliceRepr, - bad: BadSliceRepr, - addr: usize, - slice: &'static [u8], - raw_slice: *const [u8], - str: &'static str, - my_str: &'static MyStr, - my_slice: &'static MySliceBool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr { - ptr: *const u8, - vtable: *const u8, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr2 { - ptr: *const u8, - vtable: *const u64, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadDynRepr { - ptr: *const u8, - vtable: usize, -} - -#[repr(C)] -union DynTransmute { - repr: DynRepr, - repr2: DynRepr2, - bad: BadDynRepr, - addr: usize, - rust: &'static dyn Trait, - raw_rust: *const dyn Trait, +union MaybeUninit { + uninit: (), + init: T, } trait Trait {} @@ -81,90 +27,93 @@ type MySliceBool = MySlice<[bool]>; // # str // OK -const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) }; // bad str -const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad str -const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type -const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 -const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 in user-defined str-like -const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; +const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // # slice // OK -const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // bad slice: length uninit -const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // bad slice: length too big -const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad slice: length not an int -const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice -const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; //~^ ERROR it is undefined behavior to use this value // good MySliceBool const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); // bad: sized field is not okay -const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); //~^ ERROR it is undefined behavior to use this value // bad: unsized part is not okay -const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); //~^ ERROR it is undefined behavior to use this value // # raw slice -const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok -const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw -const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw -const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; +const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // # trait object // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the trait object -const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw // Const eval fails for these, so they need to be statics to error. static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) //~^ ERROR could not evaluate static initializer }; static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) //~^ ERROR could not evaluate static initializer }; -fn main() { - let _ = RAW_TRAIT_OBJ_VTABLE_NULL; - let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; -} +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 4da9ad6c332..2a3ae7dfe6d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,158 +1,166 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:86:1 + --> $DIR/ub-wide-ptr.rs:32:1 | -LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:35:1 + | +LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:38:1 + | +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:42:1 + | +LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:45:1 + | +LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:52:1 + | +LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:58:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:61:1 + | +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:65:1 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:71:1 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:74:1 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:81:1 + | +LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:89:1 | -LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:92:1 | -LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:95:1 | -LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:99:1 | -LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:106:1 + --> $DIR/ub-wide-ptr.rs:103:1 | -LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:109:1 + --> $DIR/ub-wide-ptr.rs:105:1 | -LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:112:1 - | -LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:116:1 - | -LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:122:1 - | -LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:125:1 - | -LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:132:1 - | -LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:137:1 - | -LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:140:1 - | -LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:143:1 - | -LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:147:1 - | -LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:151:1 - | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:153:1 - | -LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:159:5 + --> $DIR/ub-wide-ptr.rs:111:5 | -LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:163:5 + --> $DIR/ub-wide-ptr.rs:115:5 | -LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N +LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N error: aborting due to 20 previous errors From 4807e939cdeba02b0752ba5748eec9ef4e9f1af8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 20:52:27 +0100 Subject: [PATCH 09/17] test that we validate boxes --- src/librustc_mir/interpret/validity.rs | 1 - src/test/ui/consts/const-eval/ub-ref.rs | 13 +++++++ src/test/ui/consts/const-eval/ub-ref.stderr | 40 ++++++++++++++++++--- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index defb490199b..ee4d05c5911 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -453,7 +453,6 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(true) } ty::Adt(def, ..) if def.is_box() => { - // FIXME make sure we have a test for `Box`! self.check_safe_pointer(value)?; Ok(true) } diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 889579ca1ec..14ededafaff 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -8,9 +8,16 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value //~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) +const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) + const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + // It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, // but that would fail to compile; so we ended up breaking user code that would // have worked fine had we not promoted. @@ -20,7 +27,13 @@ const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; //~^ ERROR it is undefined behavior to use this value +const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; +//~^ ERROR it is undefined behavior to use this value + const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; //~^ ERROR it is undefined behavior to use this value +const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 5cef0a488eb..3cb91ef2752 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -9,13 +9,29 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:15:1 + | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:17:1 + --> $DIR/ub-ref.rs:18:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:24:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -23,7 +39,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:20:1 + --> $DIR/ub-ref.rs:27:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes @@ -31,13 +47,29 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:23:1 + --> $DIR/ub-ref.rs:30:1 + | +LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:33:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 5 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:36:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0080`. From f481547622722c4813f6e60bbbe55802dc688664 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:03:40 +0100 Subject: [PATCH 10/17] test some more kinds of enums with uninhabited variants --- src/test/ui/consts/const-eval/ub-enum.rs | 36 +++++++++++++- src/test/ui/consts/const-eval/ub-enum.stderr | 52 ++++++++++++++++---- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 4e7c7be4a76..1e6a670a400 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,4 +1,4 @@ -#![feature(const_transmute)] +#![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here use std::mem; @@ -7,6 +7,11 @@ use std::mem; #[derive(Copy, Clone)] struct Wrap(T); +#[derive(Copy, Clone)] +enum Never {} + +// # simple enum with discriminant 0 + #[repr(usize)] #[derive(Copy, Clone)] enum Enum { @@ -24,6 +29,8 @@ const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior +// # simple enum with discriminant 2 + // (Potentially) invalid enum discriminant #[repr(usize)] #[derive(Copy, Clone)] @@ -52,11 +59,38 @@ const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior +// # valid discriminant for uninhabited variant + +// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// have a discriminant. +enum UninhDiscriminant { + A, + B(!), + C, + D(Never), +} + +const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A +const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C + +const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; +//~^ ERROR is undefined behavior + +// # other + // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). // Need to create something which does not clash with enum layout optimizations. const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior +// All variants are uninhabited but also have data. +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior + fn main() { } diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 95d4155be91..d72884933f5 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:18:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:21:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:24:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:34:1 + --> $DIR/ub-enum.rs:41:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:36:1 + --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:39:1 + --> $DIR/ub-enum.rs:46:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:55:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:52:1 + --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,13 +63,45 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:58:1 + --> $DIR/ub-enum.rs:76:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:78:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:86:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 9 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:90:1 + | +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:92:1 + | +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0080`. From 4584e75c9b23b57c4398714406845306e7ba73c2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:17:34 +0100 Subject: [PATCH 11/17] better error messages for invalid boxes (and a few more tests) --- src/librustc_mir/interpret/validity.rs | 19 +++++---- src/test/ui/consts/const-eval/ub-ref.rs | 2 +- src/test/ui/consts/const-eval/ub-ref.stderr | 6 +-- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 6 +++ .../ui/consts/const-eval/ub-wide-ptr.stderr | 42 +++++++++++++------ 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ee4d05c5911..74a22b90a8b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -307,7 +307,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M } /// Check a reference or `Box`. - fn check_safe_pointer(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + fn check_safe_pointer( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + kind: &str, + ) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; // Handle wide pointers. // Check metadata early, for better diagnostics @@ -337,13 +341,14 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ); match err.kind { err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("a NULL reference", self.path) + throw_validation_failure!(format_args!("a NULL {}", kind), self.path) } err_unsup!(AlignmentCheckFailed { required, has }) => { throw_validation_failure!( format_args!( - "an unaligned reference \ + "an unaligned {} \ (required {} byte alignment but found {})", + kind, required.bytes(), has.bytes() ), @@ -351,11 +356,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ) } err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "a dangling reference (created from integer)", + format_args!("a dangling {} (created from integer)", kind), self.path ), _ => throw_validation_failure!( - "a dangling reference (not entirely in bounds)", + format_args!("a dangling {} (not entirely in bounds)", kind), self.path ), } @@ -449,11 +454,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(true) } ty::Ref(..) => { - self.check_safe_pointer(value)?; + self.check_safe_pointer(value, "reference")?; Ok(true) } ty::Adt(def, ..) if def.is_box() => { - self.check_safe_pointer(value)?; + self.check_safe_pointer(value, "box")?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 14ededafaff..562ec99111b 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -10,7 +10,7 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value -//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) +//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1) const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 3cb91ef2752..fb3df8ace4e 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:18:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:36:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index ada82fc83a8..26d37884746 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -60,6 +60,12 @@ const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // bad slice: length not an int const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value +// bad slice box: length too big +const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length not an int +const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 2a3ae7dfe6d..22adf0e55ee 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -67,7 +67,23 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:65:1 + --> $DIR/ub-wide-ptr.rs:64:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:67:1 + | +LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:71:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean @@ -75,7 +91,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:71:1 + --> $DIR/ub-wide-ptr.rs:77:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean @@ -83,7 +99,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:74:1 + --> $DIR/ub-wide-ptr.rs:80:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean @@ -91,7 +107,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:81:1 + --> $DIR/ub-wide-ptr.rs:87:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -103,7 +119,7 @@ LL | | }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:89:1 + --> $DIR/ub-wide-ptr.rs:95:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +127,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:92:1 + --> $DIR/ub-wide-ptr.rs:98:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +135,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:95:1 + --> $DIR/ub-wide-ptr.rs:101:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -127,7 +143,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4u = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:99:1 + --> $DIR/ub-wide-ptr.rs:105:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean @@ -135,7 +151,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -143,7 +159,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:105:1 + --> $DIR/ub-wide-ptr.rs:111:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -151,17 +167,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:111:5 + --> $DIR/ub-wide-ptr.rs:117:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:115:5 + --> $DIR/ub-wide-ptr.rs:121:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0080`. From f0586f9aea1948fe208751f8183d58f9af1116b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:53:58 +0100 Subject: [PATCH 12/17] please tidy --- src/test/ui/consts/const-eval/ub-enum.rs | 1 + src/test/ui/consts/const-eval/ub-enum.stderr | 26 ++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 1e6a670a400..499be5107f9 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength #![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index d72884933f5..e0cf2cd610f 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:23:1 + --> $DIR/ub-enum.rs:24:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:26:1 + --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:41:1 + --> $DIR/ub-enum.rs:42:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:43:1 + --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:46:1 + --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:55:1 + --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:59:1 + --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,7 +63,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:76:1 + --> $DIR/ub-enum.rs:77:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 @@ -71,7 +71,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:78:1 + --> $DIR/ub-enum.rs:79:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 @@ -79,7 +79,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:86:1 + --> $DIR/ub-enum.rs:87:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint @@ -87,7 +87,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:90:1 + --> $DIR/ub-enum.rs:91:1 | LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 @@ -95,7 +95,7 @@ LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:92:1 + --> $DIR/ub-enum.rs:93:1 | LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 From 58f8cc21352613639fdc58f4f8a59f5c579b5372 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 22:24:23 +0100 Subject: [PATCH 13/17] rename visit_primitive -> try_visit_primitive, and comments --- src/librustc_mir/interpret/validity.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 74a22b90a8b..29d18e87c4f 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -406,7 +406,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { + fn try_visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { @@ -477,7 +477,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // Nothing to check. Ok(true) } - // This should be all the (inhabited) primitive types. The rest is compound, we + // The above should be all the (inhabited) primitive types. The rest is compound, we // check them by visiting their fields/variants. // (`Str` UTF-8 check happens in `visit_aggregate`, too.) ty::Adt(..) @@ -489,7 +489,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => Ok(false), - // Some types only occur during inference, we should not see them here. + // Some types only occur during typechecking, they have no layout. + // We should not see them here and we could not check them anyway. ty::Error | ty::Infer(..) | ty::Placeholder(..) @@ -618,7 +619,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> trace!("visit_value: {:?}, {:?}", *op, op.layout); // Check primitive types -- the leafs of our recursive descend. - if self.visit_primitive(op)? { + if self.try_visit_primitive(op)? { return Ok(()); } // Sanity check: `builtin_deref` does not know any pointers that are not primitive. From 295c2d69bd425e8258f197252d2f100e08f478d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 22:47:28 +0100 Subject: [PATCH 14/17] bug on ty::GeneratorWitness --- src/librustc_mir/interpret/validity.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 29d18e87c4f..0fba8a5c15c 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -406,7 +406,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. - fn try_visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { + fn try_visit_primitive( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { @@ -487,8 +490,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Str | ty::Dynamic(..) | ty::Closure(..) - | ty::Generator(..) - | ty::GeneratorWitness(..) => Ok(false), + | ty::Generator(..) => Ok(false), // Some types only occur during typechecking, they have no layout. // We should not see them here and we could not check them anyway. ty::Error @@ -498,7 +500,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Param(..) | ty::Opaque(..) | ty::UnnormalizedProjection(..) - | ty::Projection(..) => bug!("Encountered invalid type {:?}", ty), + | ty::Projection(..) + | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), } } From b1b558f1f0cf5caab5c44c88e7050cba71c6be0d Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 7 Mar 2020 16:58:29 +0100 Subject: [PATCH 15/17] refactor: Exhaustive matching in method/probe.rs --- src/librustc_typeck/check/method/probe.rs | 116 ++++++++-------------- 1 file changed, 40 insertions(+), 76 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a52cabd8894..179ed2f55d5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -572,7 +572,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates(&mut self) { - let steps = self.steps.clone(); + let steps = Lrc::clone(&self.steps); for step in steps.iter() { self.assemble_probe(&step.self_ty); } @@ -635,87 +635,51 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::Slice(_) => { - let lang_def_id = lang_items.slice_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_u8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_alloc_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_u8_alloc_impl(); + for &lang_def_id in &[ + lang_items.slice_impl(), + lang_items.slice_u8_impl(), + lang_items.slice_alloc_impl(), + lang_items.slice_u8_alloc_impl(), + ] { + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + } + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => { + let lang_def_id = match mutbl { + hir::Mutability::Not => lang_items.const_ptr_impl(), + hir::Mutability::Mut => lang_items.mut_ptr_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { - let lang_def_id = lang_items.const_ptr_impl(); + ty::Int(i) => { + let lang_def_id = match i { + ast::IntTy::I8 => lang_items.i8_impl(), + ast::IntTy::I16 => lang_items.i16_impl(), + ast::IntTy::I32 => lang_items.i32_impl(), + ast::IntTy::I64 => lang_items.i64_impl(), + ast::IntTy::I128 => lang_items.i128_impl(), + ast::IntTy::Isize => lang_items.isize_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { - let lang_def_id = lang_items.mut_ptr_impl(); + ty::Uint(i) => { + let lang_def_id = match i { + ast::UintTy::U8 => lang_items.u8_impl(), + ast::UintTy::U16 => lang_items.u16_impl(), + ast::UintTy::U32 => lang_items.u32_impl(), + ast::UintTy::U64 => lang_items.u64_impl(), + ast::UintTy::U128 => lang_items.u128_impl(), + ast::UintTy::Usize => lang_items.usize_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::Int(ast::IntTy::I8) => { - let lang_def_id = lang_items.i8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I16) => { - let lang_def_id = lang_items.i16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I32) => { - let lang_def_id = lang_items.i32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I64) => { - let lang_def_id = lang_items.i64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I128) => { - let lang_def_id = lang_items.i128_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::Isize) => { - let lang_def_id = lang_items.isize_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U8) => { - let lang_def_id = lang_items.u8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U16) => { - let lang_def_id = lang_items.u16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U32) => { - let lang_def_id = lang_items.u32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U64) => { - let lang_def_id = lang_items.u64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U128) => { - let lang_def_id = lang_items.u128_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::Usize) => { - let lang_def_id = lang_items.usize_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Float(ast::FloatTy::F32) => { - let lang_def_id = lang_items.f32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.f32_runtime_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Float(ast::FloatTy::F64) => { - let lang_def_id = lang_items.f64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.f64_runtime_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + ty::Float(f) => { + let (lang_def_id1, lang_def_id2) = match f { + ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()), + ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()), + }; + self.assemble_inherent_impl_for_primitive(lang_def_id1); + self.assemble_inherent_impl_for_primitive(lang_def_id2); } _ => {} } From 6095fa146ce994c1650376257ab488156e6e745a Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 7 Mar 2020 20:17:00 +0100 Subject: [PATCH 16/17] refactor: Move a borrow_mut and unwrap out of a loop --- src/librustc_typeck/check/method/mod.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 9b8d88e94b6..542a1ac4536 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -459,12 +459,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::TraitsInScope, )?; debug!("resolve_ufcs: pick={:?}", pick); - for import_id in pick.import_ids { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap() - .insert(import_def_id); + { + let mut tables = self.tables.borrow_mut(); + let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap(); + for import_id in pick.import_ids { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + used_trait_imports.insert(import_def_id); + } } let def_kind = pick.item.def_kind(); From a95f00fe1b064f548b6513fbf88afc223f6c4f9c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Mar 2020 12:22:20 +0100 Subject: [PATCH 17/17] fix type size mismatch on 32bit --- src/test/ui/consts/const-eval/ub-enum.rs | 5 ++- src/test/ui/consts/const-eval/ub-enum.stderr | 34 ++++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 499be5107f9..1922d59891f 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here @@ -88,9 +87,9 @@ const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute //~^ ERROR is undefined behavior // All variants are uninhabited but also have data. -const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) }; //~^ ERROR is undefined behavior -const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) }; //~^ ERROR is undefined behavior fn main() { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index e0cf2cd610f..10a3d2fa1ab 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:24:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:27:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:30:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:42:1 + --> $DIR/ub-enum.rs:41:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:44:1 + --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:47:1 + --> $DIR/ub-enum.rs:46:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:56:1 + --> $DIR/ub-enum.rs:55:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:60:1 + --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,7 +63,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:77:1 + --> $DIR/ub-enum.rs:76:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 @@ -71,7 +71,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:79:1 + --> $DIR/ub-enum.rs:78:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 @@ -79,7 +79,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:87:1 + --> $DIR/ub-enum.rs:86:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint @@ -87,18 +87,18 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:91:1 + --> $DIR/ub-enum.rs:90:1 | -LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:93:1 + --> $DIR/ub-enum.rs:92:1 | -LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.