Auto merge of #69829 - Centril:rollup-lm5lzsq, r=Centril
Rollup of 7 pull requests Successful merges: - #69631 (remove non-sysroot sources from rust-src component) - #69646 (Miri visitor: detect primitive types based on type, not layout (also, more tests)) - #69651 (Try to ensure usize marker does not get merged) - #69668 (More documentation and simplification of BTreeMap's internals) - #69771 (Cleanup E0390 explanation) - #69777 (Add missing ` in doc for File::with_options()) - #69812 (Refactorings to method/probe.rs and CrateId) Failed merges: r? @ghost
This commit is contained in:
commit
564758c4c3
21 changed files with 603 additions and 506 deletions
|
@ -1002,8 +1002,6 @@ impl Step for Src {
|
||||||
"src/tools/rustc-std-workspace-core",
|
"src/tools/rustc-std-workspace-core",
|
||||||
"src/tools/rustc-std-workspace-alloc",
|
"src/tools/rustc-std-workspace-alloc",
|
||||||
"src/tools/rustc-std-workspace-std",
|
"src/tools/rustc-std-workspace-std",
|
||||||
"src/librustc",
|
|
||||||
"src/librustc_ast",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src);
|
copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src);
|
||||||
|
|
|
@ -153,10 +153,15 @@ impl<K, V> InternalNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An owned pointer to a node. This basically is either `Box<LeafNode<K, V>>` or
|
/// A managed, non-null pointer to a node. This is either an owned pointer to
|
||||||
/// `Box<InternalNode<K, V>>`. However, it contains no information as to which of the two types
|
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
|
||||||
/// of nodes is actually behind the box, and, partially due to this lack of information, has no
|
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
|
||||||
/// destructor.
|
/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at
|
||||||
|
/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
|
||||||
|
/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'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<K, V> {
|
struct BoxedNode<K, V> {
|
||||||
ptr: Unique<LeafNode<K, V>>,
|
ptr: Unique<LeafNode<K, V>>,
|
||||||
}
|
}
|
||||||
|
@ -167,9 +172,7 @@ impl<K, V> BoxedNode<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
|
fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
|
||||||
unsafe {
|
BoxedNode { ptr: Box::into_unique(node).cast() }
|
||||||
BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
|
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
|
||||||
|
@ -181,10 +184,11 @@ impl<K, V> BoxedNode<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An owned tree. Note that despite being owned, this does not have a destructor,
|
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor,
|
||||||
/// and must be cleaned up manually.
|
/// and must be cleaned up manually if it is an owned tree.
|
||||||
pub struct Root<K, V> {
|
pub struct Root<K, V> {
|
||||||
node: BoxedNode<K, V>,
|
node: BoxedNode<K, V>,
|
||||||
|
/// The number of levels below the root node.
|
||||||
height: usize,
|
height: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,21 +196,21 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
|
||||||
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
|
||||||
|
|
||||||
impl<K, V> Root<K, V> {
|
impl<K, V> Root<K, V> {
|
||||||
|
/// 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 {
|
pub fn is_shared_root(&self) -> bool {
|
||||||
self.as_ref().is_shared_root()
|
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 {
|
pub fn shared_empty_root() -> Self {
|
||||||
Root {
|
Root {
|
||||||
node: unsafe {
|
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
|
||||||
BoxedNode::from_ptr(NonNull::new_unchecked(
|
|
||||||
&EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _,
|
|
||||||
))
|
|
||||||
},
|
|
||||||
height: 0,
|
height: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new owned tree, with its own root node that is initially empty.
|
||||||
pub fn new_leaf() -> Self {
|
pub fn new_leaf() -> Self {
|
||||||
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
|
||||||
}
|
}
|
||||||
|
@ -310,6 +314,7 @@ impl<K, V> Root<K, V> {
|
||||||
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
|
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
|
||||||
/// Turning this into a `NodeHeader` reference is always safe.
|
/// Turning this into a `NodeHeader` reference is always safe.
|
||||||
pub struct NodeRef<BorrowType, K, V, Type> {
|
pub struct NodeRef<BorrowType, K, V, Type> {
|
||||||
|
/// The number of levels below the node.
|
||||||
height: usize,
|
height: usize,
|
||||||
node: NonNull<LeafNode<K, V>>,
|
node: NonNull<LeafNode<K, V>>,
|
||||||
// `root` is null unless the borrow type is `Mut`
|
// `root` is null unless the borrow type is `Mut`
|
||||||
|
|
|
@ -264,8 +264,18 @@ pub struct ArgumentV1<'a> {
|
||||||
// could have been miscompiled. In practice, we never call as_usize on non-usize
|
// 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
|
// containing data (as a matter of static generation of the formatting
|
||||||
// arguments), so this is merely an additional check.
|
// 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")]
|
#[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> {
|
impl<'a> ArgumentV1<'a> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -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
|
```compile_fail,E0390
|
||||||
struct Foo {
|
struct Foo {
|
||||||
|
|
|
@ -306,23 +306,127 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||||
Ok(())
|
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>,
|
||||||
|
kind: &str,
|
||||||
|
) -> InterpResult<'tcx> {
|
||||||
let value = self.ecx.read_immediate(value)?;
|
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!(format_args!("a NULL {}", kind), self.path)
|
||||||
|
}
|
||||||
|
err_unsup!(AlignmentCheckFailed { required, has }) => {
|
||||||
|
throw_validation_failure!(
|
||||||
|
format_args!(
|
||||||
|
"an unaligned {} \
|
||||||
|
(required {} byte alignment but found {})",
|
||||||
|
kind,
|
||||||
|
required.bytes(),
|
||||||
|
has.bytes()
|
||||||
|
),
|
||||||
|
self.path
|
||||||
|
)
|
||||||
|
}
|
||||||
|
err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
|
||||||
|
format_args!("a dangling {} (created from integer)", kind),
|
||||||
|
self.path
|
||||||
|
),
|
||||||
|
_ => throw_validation_failure!(
|
||||||
|
format_args!("a dangling {} (not entirely in bounds)", kind),
|
||||||
|
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 try_visit_primitive(
|
||||||
|
&mut self,
|
||||||
|
value: OpTy<'tcx, M::PointerTag>,
|
||||||
|
) -> InterpResult<'tcx, bool> {
|
||||||
// Go over all the primitive types
|
// Go over all the primitive types
|
||||||
let ty = value.layout.ty;
|
let ty = value.layout.ty;
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
ty::Bool => {
|
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");
|
try_validation!(value.to_bool(), value, self.path, "a boolean");
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
ty::Char => {
|
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");
|
try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint");
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
|
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
|
// NOTE: Keep this in sync with the array optimization for int/float
|
||||||
// types below!
|
// types below!
|
||||||
let value = value.to_scalar_or_undef();
|
|
||||||
if self.ref_tracking_for_consts.is_some() {
|
if self.ref_tracking_for_consts.is_some() {
|
||||||
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
|
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
|
||||||
let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
|
let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
|
||||||
|
@ -337,108 +441,31 @@ 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
|
// At run-time, for now, we accept *anything* for these types, including
|
||||||
// undef. We should fix that, but let's start low.
|
// undef. We should fix that, but let's start low.
|
||||||
}
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
ty::RawPtr(..) => {
|
ty::RawPtr(..) => {
|
||||||
// We are conservative with undef for integers, but try to
|
// We are conservative with undef for integers, but try to
|
||||||
// actually enforce our current rules for raw pointers.
|
// actually enforce our current rules for raw pointers.
|
||||||
let place =
|
let place = try_validation!(
|
||||||
try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
|
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
|
||||||
|
"undefined pointer",
|
||||||
|
self.path
|
||||||
|
);
|
||||||
if place.layout.is_unsized() {
|
if place.layout.is_unsized() {
|
||||||
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
||||||
}
|
}
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
_ if ty.is_box() || ty.is_region_ptr() => {
|
ty::Ref(..) => {
|
||||||
// Handle wide pointers.
|
self.check_safe_pointer(value, "reference")?;
|
||||||
// Check metadata early, for better diagnostics
|
Ok(true)
|
||||||
let place =
|
}
|
||||||
try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
|
ty::Adt(def, ..) if def.is_box() => {
|
||||||
if place.layout.is_unsized() {
|
self.check_safe_pointer(value, "box")?;
|
||||||
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
Ok(true)
|
||||||
}
|
|
||||||
// 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::FnPtr(_sig) => {
|
ty::FnPtr(_sig) => {
|
||||||
let value = value.to_scalar_or_undef();
|
let value = self.ecx.read_scalar(value)?;
|
||||||
let _fn = try_validation!(
|
let _fn = try_validation!(
|
||||||
value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
|
value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
|
||||||
value,
|
value,
|
||||||
|
@ -446,11 +473,36 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||||
"a function pointer"
|
"a function pointer"
|
||||||
);
|
);
|
||||||
// FIXME: Check if the signature matches
|
// FIXME: Check if the signature matches
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
// This should be all the (inhabited) primitive types
|
ty::Never => throw_validation_failure!("a value of the never type `!`", self.path),
|
||||||
_ => bug!("Unexpected primitive type {}", value.layout.ty),
|
ty::Foreign(..) | ty::FnDef(..) => {
|
||||||
|
// Nothing to check.
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
// 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(..)
|
||||||
|
| ty::Tuple(..)
|
||||||
|
| ty::Array(..)
|
||||||
|
| ty::Slice(..)
|
||||||
|
| ty::Str
|
||||||
|
| ty::Dynamic(..)
|
||||||
|
| ty::Closure(..)
|
||||||
|
| 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
|
||||||
|
| ty::Infer(..)
|
||||||
|
| ty::Placeholder(..)
|
||||||
|
| ty::Bound(..)
|
||||||
|
| ty::Param(..)
|
||||||
|
| ty::Opaque(..)
|
||||||
|
| ty::UnnormalizedProjection(..)
|
||||||
|
| ty::Projection(..)
|
||||||
|
| ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_scalar(
|
fn visit_scalar(
|
||||||
|
@ -558,11 +610,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> {
|
fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> {
|
||||||
// Empty unions are not accepted by rustc. That's great, it means we can
|
// Empty unions are not accepted by rustc. But uninhabited enums
|
||||||
// use that as a signal for detecting primitives. Make sure
|
// claim to be unions, so allow them, too.
|
||||||
// we did not miss any primitive.
|
assert!(op.layout.abi.is_uninhabited() || fields > 0);
|
||||||
assert!(fields > 0);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,29 +621,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> {
|
fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
|
||||||
trace!("visit_value: {:?}, {:?}", *op, op.layout);
|
trace!("visit_value: {:?}, {:?}", *op, op.layout);
|
||||||
|
|
||||||
if op.layout.abi.is_uninhabited() {
|
// Check primitive types -- the leafs of our recursive descend.
|
||||||
// Uninhabited types do not have sensible layout, stop right here.
|
if self.try_visit_primitive(op)? {
|
||||||
throw_validation_failure!(
|
return Ok(());
|
||||||
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 fieldless 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(),
|
|
||||||
};
|
|
||||||
if primitive {
|
|
||||||
// No need to recurse further or check scalar layout, this is a leaf type.
|
|
||||||
return self.visit_primitive(op);
|
|
||||||
}
|
}
|
||||||
|
// 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.
|
// Recursively walk the type. Translate some possible errors to something nicer.
|
||||||
match self.walk_value(op) {
|
match self.walk_value(op) {
|
||||||
|
@ -619,7 +653,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
|
// scalars, we do the same check on every "level" (e.g., first we check
|
||||||
// MyNewtype and then the scalar in there).
|
// MyNewtype and then the scalar in there).
|
||||||
match op.layout.abi {
|
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) => {
|
layout::Abi::Scalar(ref scalar_layout) => {
|
||||||
self.visit_scalar(op, scalar_layout)?;
|
self.visit_scalar(op, scalar_layout)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -872,7 +872,7 @@ impl Niche {
|
||||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct LayoutDetails {
|
pub struct LayoutDetails {
|
||||||
/// Says where the fields are located within the layout.
|
/// 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,
|
pub fields: FieldPlacement,
|
||||||
|
|
||||||
/// Encodes information about multi-variant layouts.
|
/// Encodes information about multi-variant layouts.
|
||||||
|
|
|
@ -459,12 +459,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ProbeScope::TraitsInScope,
|
ProbeScope::TraitsInScope,
|
||||||
)?;
|
)?;
|
||||||
debug!("resolve_ufcs: pick={:?}", pick);
|
debug!("resolve_ufcs: pick={:?}", pick);
|
||||||
for import_id in pick.import_ids {
|
{
|
||||||
let import_def_id = tcx.hir().local_def_id(import_id);
|
let mut tables = self.tables.borrow_mut();
|
||||||
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
|
let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap();
|
||||||
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
|
for import_id in pick.import_ids {
|
||||||
.unwrap()
|
let import_def_id = tcx.hir().local_def_id(import_id);
|
||||||
.insert(import_def_id);
|
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
|
||||||
|
used_trait_imports.insert(import_def_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_kind = pick.item.def_kind();
|
let def_kind = pick.item.def_kind();
|
||||||
|
|
|
@ -572,7 +572,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_inherent_candidates(&mut self) {
|
fn assemble_inherent_candidates(&mut self) {
|
||||||
let steps = self.steps.clone();
|
let steps = Lrc::clone(&self.steps);
|
||||||
for step in steps.iter() {
|
for step in steps.iter() {
|
||||||
self.assemble_probe(&step.self_ty);
|
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);
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
}
|
}
|
||||||
ty::Slice(_) => {
|
ty::Slice(_) => {
|
||||||
let lang_def_id = lang_items.slice_impl();
|
for &lang_def_id in &[
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
lang_items.slice_impl(),
|
||||||
|
lang_items.slice_u8_impl(),
|
||||||
let lang_def_id = lang_items.slice_u8_impl();
|
lang_items.slice_alloc_impl(),
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
lang_items.slice_u8_alloc_impl(),
|
||||||
|
] {
|
||||||
let lang_def_id = lang_items.slice_alloc_impl();
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
}
|
||||||
|
}
|
||||||
let lang_def_id = lang_items.slice_u8_alloc_impl();
|
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);
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
|
ty::Int(i) => {
|
||||||
let lang_def_id = lang_items.const_ptr_impl();
|
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);
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
|
ty::Uint(i) => {
|
||||||
let lang_def_id = lang_items.mut_ptr_impl();
|
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);
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I8) => {
|
ty::Float(f) => {
|
||||||
let lang_def_id = lang_items.i8_impl();
|
let (lang_def_id1, lang_def_id2) = match f {
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()),
|
||||||
}
|
ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()),
|
||||||
ty::Int(ast::IntTy::I16) => {
|
};
|
||||||
let lang_def_id = lang_items.i16_impl();
|
self.assemble_inherent_impl_for_primitive(lang_def_id1);
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
self.assemble_inherent_impl_for_primitive(lang_def_id2);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -407,7 +407,7 @@ impl File {
|
||||||
///
|
///
|
||||||
/// It is equivalent to `OpenOptions::new()` but allows you to write more
|
/// It is equivalent to `OpenOptions::new()` but allows you to write more
|
||||||
/// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
|
/// 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`.
|
/// also avoids the need to import `OpenOptions`.
|
||||||
///
|
///
|
||||||
/// See the [`OpenOptions::new`] function for more details.
|
/// See the [`OpenOptions::new`] function for more details.
|
||||||
|
|
|
@ -1,34 +1,36 @@
|
||||||
|
#![feature(const_transmute, never_type)]
|
||||||
#![allow(const_err)] // make sure we cannot allow away the errors tested here
|
#![allow(const_err)] // make sure we cannot allow away the errors tested here
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Wrap<T>(T);
|
struct Wrap<T>(T);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum Never {}
|
||||||
|
|
||||||
|
// # simple enum with discriminant 0
|
||||||
|
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
A = 0,
|
A = 0,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
|
||||||
union TransmuteEnum {
|
|
||||||
in1: &'static u8,
|
|
||||||
in2: usize,
|
|
||||||
out1: Enum,
|
|
||||||
out2: Wrap<Enum>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
//~^ 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
|
//~^ ERROR is undefined behavior
|
||||||
|
|
||||||
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
|
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR is undefined behavior
|
||||||
|
|
||||||
|
// # simple enum with discriminant 2
|
||||||
|
|
||||||
// (Potentially) invalid enum discriminant
|
// (Potentially) invalid enum discriminant
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -36,39 +38,58 @@ enum Enum2 {
|
||||||
A = 2,
|
A = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
|
||||||
union TransmuteEnum2 {
|
|
||||||
in1: usize,
|
|
||||||
in2: &'static u8,
|
|
||||||
in3: (),
|
|
||||||
out1: Enum2,
|
|
||||||
out2: Wrap<Enum2>, // something wrapping the enum so that we test layout first, not enum
|
|
||||||
out3: Option<Enum2>,
|
|
||||||
}
|
|
||||||
const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
|
|
||||||
//~^ ERROR is undefined behavior
|
//~^ 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
|
//~^ ERROR is undefined behavior
|
||||||
const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
|
// something wrapping the enum so that we test layout first, not enum
|
||||||
|
const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR is undefined behavior
|
||||||
|
|
||||||
// Undef enum discriminant.
|
// Undef enum discriminant.
|
||||||
const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
|
#[repr(C)]
|
||||||
|
union MaybeUninit<T: Copy> {
|
||||||
|
uninit: (),
|
||||||
|
init: T,
|
||||||
|
}
|
||||||
|
const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR is undefined behavior
|
||||||
|
|
||||||
// Pointer value in an enum with a niche that is not just 0.
|
// Pointer value in an enum with a niche that is not just 0.
|
||||||
const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
|
const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ 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
|
// Invalid enum field content (mostly to test printing of paths for enum tuple
|
||||||
// variants and tuples).
|
// variants and tuples).
|
||||||
#[repr(C)]
|
|
||||||
union TransmuteChar {
|
|
||||||
a: u32,
|
|
||||||
b: char,
|
|
||||||
}
|
|
||||||
// Need to create something which does not clash with enum layout optimizations.
|
// 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
|
||||||
|
|
||||||
|
// All variants are uninhabited but also have data.
|
||||||
|
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(1u64) };
|
||||||
//~^ ERROR is undefined behavior
|
//~^ ERROR is undefined behavior
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,75 +1,107 @@
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:23:1
|
--> $DIR/ub-enum.rs:23:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:26:1
|
--> $DIR/ub-enum.rs:26:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:29:1
|
--> $DIR/ub-enum.rs:29:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:48:1
|
--> $DIR/ub-enum.rs:41:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:50:1
|
--> $DIR/ub-enum.rs:43:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:52:1
|
--> $DIR/ub-enum.rs:46:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, 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.
|
= 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
|
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 { TransmuteEnum2 { in3: () }.out1 };
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .<enum-tag>, 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.
|
= 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
|
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<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-enum.rs:71:1
|
--> $DIR/ub-enum.rs:76:1
|
||||||
|
|
|
|
||||||
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<enum-variant(Some)>.0.1, but expected a valid unicode codepoint
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(B)>.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.
|
= 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:78:1
|
||||||
|
|
|
||||||
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(D)>.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 .<enum-variant(Some)>.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[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(1u64) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<enum-variant(Err)>.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(1u64) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at .<enum-variant(Err)>.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`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -25,11 +25,11 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
union Transmute {
|
union MaybeUninit<T: Copy> {
|
||||||
uninit: (),
|
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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// Also test other uses of rustc_layout_scalar_valid_range_start
|
// Also test other uses of rustc_layout_scalar_valid_range_start
|
||||||
|
|
|
@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-nonnull.rs:32:1
|
--> $DIR/ub-nonnull.rs:32:1
|
||||||
|
|
|
|
||||||
LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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.
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,16 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ 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 reference (required 2 byte alignment but found 1)
|
||||||
|
|
||||||
|
const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
|
||||||
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
|
||||||
|
|
||||||
const NULL: &u16 = unsafe { mem::transmute(0usize) };
|
const NULL: &u16 = unsafe { mem::transmute(0usize) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
|
const NULL_BOX: Box<u16> = 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)`,
|
// 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
|
// but that would fail to compile; so we ended up breaking user code that would
|
||||||
// have worked fine had we not promoted.
|
// 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) }];
|
const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ 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) };
|
const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
|
const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
|
||||||
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -9,13 +9,29 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-ref.rs:11:1
|
--> $DIR/ub-ref.rs:11:1
|
||||||
|
|
|
|
||||||
|
LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||||
|
|
||||||
|
error[E0080]: it is undefined behavior to use this value
|
||||||
|
--> $DIR/ub-ref.rs:15:1
|
||||||
|
|
|
||||||
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
|
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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<u16> = unsafe { mem::transmute(0usize) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||||
|
|
||||||
|
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) };
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
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) }];
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, 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.
|
= 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
|
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 .<deref>, 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) };
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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<u8> = unsafe { mem::transmute(1337usize) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -7,18 +7,18 @@ use std::mem;
|
||||||
enum Bar {}
|
enum Bar {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
union TransmuteUnion<A: Clone + Copy, B: Clone + Copy> {
|
union MaybeUninit<T: Copy> {
|
||||||
a: A,
|
uninit: (),
|
||||||
b: B,
|
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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
|
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-uninhabit.rs:15:1
|
--> $DIR/ub-uninhabit.rs:15:1
|
||||||
|
|
|
|
||||||
LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
|
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-uninhabit.rs:21:1
|
--> $DIR/ub-uninhabit.rs:21:1
|
||||||
|
|
|
|
||||||
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
|
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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.
|
||||||
|
|
||||||
|
|
|
@ -1,72 +1,18 @@
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
#![feature(const_transmute)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![allow(const_err)] // make sure we cannot allow away the errors tested here
|
#![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 "offset \d+" -> "offset N"
|
||||||
// normalize-stderr-test "allocation \d+" -> "allocation N"
|
// normalize-stderr-test "allocation \d+" -> "allocation N"
|
||||||
// normalize-stderr-test "size \d+" -> "size N"
|
// normalize-stderr-test "size \d+" -> "size N"
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
union BoolTransmute {
|
union MaybeUninit<T: Copy> {
|
||||||
val: u8,
|
uninit: (),
|
||||||
bl: bool,
|
init: T,
|
||||||
}
|
|
||||||
|
|
||||||
#[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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Trait {}
|
trait Trait {}
|
||||||
|
@ -81,90 +27,99 @@ type MySliceBool = MySlice<[bool]>;
|
||||||
|
|
||||||
// # str
|
// # str
|
||||||
// OK
|
// 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
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad str
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad str in user-defined unsized type
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// invalid UTF-8
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// invalid UTF-8 in user-defined str-like
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// # slice
|
// # slice
|
||||||
// OK
|
// 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
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
let uninit_len = MaybeUninit::<usize> { uninit: () };
|
||||||
|
mem::transmute((42, uninit_len))
|
||||||
|
};
|
||||||
// bad slice: length too big
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad slice: length not an int
|
// 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 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// bad data *inside* the slice
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// good MySliceBool
|
// good MySliceBool
|
||||||
const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
|
const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
|
||||||
// bad: sized field is not okay
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad: unsized part is not okay
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// # raw slice
|
// # raw slice
|
||||||
const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok
|
const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
|
||||||
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw
|
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // 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_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw
|
||||||
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
|
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
let uninit_len = MaybeUninit::<usize> { uninit: () };
|
||||||
|
mem::transmute((42, uninit_len))
|
||||||
|
};
|
||||||
|
|
||||||
// # trait object
|
// # trait object
|
||||||
// bad 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad trait object
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
// bad trait object
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// bad data *inside* the trait object
|
// 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
|
//~^ ERROR it is undefined behavior to use this value
|
||||||
|
|
||||||
// # raw trait object
|
// # 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
|
//~^ 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
|
//~^ 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.
|
// 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 {
|
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
|
//~^ ERROR could not evaluate static initializer
|
||||||
};
|
};
|
||||||
static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
|
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
|
//~^ ERROR could not evaluate static initializer
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
let _ = RAW_TRAIT_OBJ_VTABLE_NULL;
|
|
||||||
let _ = RAW_TRAIT_OBJ_VTABLE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,159 +1,183 @@
|
||||||
error[E0080]: it is undefined behavior to use this value
|
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};
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:89:1
|
--> $DIR/ub-wide-ptr.rs:35:1
|
||||||
|
|
|
|
||||||
LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:92:1
|
--> $DIR/ub-wide-ptr.rs:38:1
|
||||||
|
|
|
|
||||||
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:96:1
|
--> $DIR/ub-wide-ptr.rs:42:1
|
||||||
|
|
|
|
||||||
LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
|
LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
|
||||||
|
|
|
|
||||||
= 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:99:1
|
--> $DIR/ub-wide-ptr.rs:45:1
|
||||||
|
|
|
|
||||||
LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
|
LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:106:1
|
--> $DIR/ub-wide-ptr.rs:52:1
|
||||||
|
|
|
|
||||||
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
|
LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
|
LL | |
|
||||||
|
LL | | let uninit_len = MaybeUninit::<usize> { 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: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 .<deref>[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:77:1
|
||||||
|
|
|
||||||
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.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:80:1
|
||||||
|
|
|
||||||
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.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:87:1
|
||||||
|
|
|
||||||
|
LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||||
|
LL | |
|
||||||
|
LL | | let uninit_len = MaybeUninit::<usize> { 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: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
|
||||||
|
|
|
||||||
|
= 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: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
|
||||||
|
|
|
||||||
|
= 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: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
|
||||||
|
|
|
||||||
|
= 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
|
||||||
|
|
|
||||||
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:109:1
|
--> $DIR/ub-wide-ptr.rs:109:1
|
||||||
|
|
|
|
||||||
LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
|
= 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
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/ub-wide-ptr.rs:112:1
|
--> $DIR/ub-wide-ptr.rs:111:1
|
||||||
|
|
|
|
||||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:116:1
|
|
||||||
|
|
|
||||||
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>[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 .<deref>.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 .<deref>.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 .<deref>.<dyn-downcast>, 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
|
|
||||||
|
|
|
|
||||||
= 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.
|
= 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
|
error[E0080]: could not evaluate static initializer
|
||||||
--> $DIR/ub-wide-ptr.rs:159:5
|
--> $DIR/ub-wide-ptr.rs:117:5
|
||||||
|
|
|
|
||||||
LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
|
||||||
|
|
||||||
error[E0080]: could not evaluate static initializer
|
error[E0080]: could not evaluate static initializer
|
||||||
--> $DIR/ub-wide-ptr.rs:163:5
|
--> $DIR/ub-wide-ptr.rs:121:5
|
||||||
|
|
|
|
||||||
LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
|
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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/validate_uninhabited_zsts.rs:17:1
|
--> $DIR/validate_uninhabited_zsts.rs:17:1
|
||||||
|
|
|
|
||||||
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
|
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.
|
= 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.
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/validate_never_arrays.rs:3:1
|
--> $DIR/validate_never_arrays.rs:3:1
|
||||||
|
|
|
|
||||||
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
|
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at .<deref>
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[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.
|
= 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
|
--> $DIR/validate_never_arrays.rs:6:1
|
||||||
|
|
|
|
||||||
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
|
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .<deref>[0]
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[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.
|
= 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
|
--> $DIR/validate_never_arrays.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
|
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .<deref>[0]
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .<deref>[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.
|
= 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.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue