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:
bors 2020-03-08 15:54:09 +00:00
commit 564758c4c3
21 changed files with 603 additions and 506 deletions

View File

@ -1002,8 +1002,6 @@ impl Step for Src {
"src/tools/rustc-std-workspace-core",
"src/tools/rustc-std-workspace-alloc",
"src/tools/rustc-std-workspace-std",
"src/librustc",
"src/librustc_ast",
];
copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src);

View File

@ -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
/// `Box<InternalNode<K, V>>`. However, it contains no information as to which of the two types
/// of nodes is actually behind the box, and, partially due to this lack of information, has no
/// destructor.
/// A managed, non-null pointer to a node. This is either an owned pointer to
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
/// 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> {
ptr: Unique<LeafNode<K, V>>,
}
@ -167,9 +172,7 @@ impl<K, V> BoxedNode<K, V> {
}
fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
unsafe {
BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
}
BoxedNode { ptr: Box::into_unique(node).cast() }
}
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,
/// and must be cleaned up manually.
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor,
/// and must be cleaned up manually if it is an owned tree.
pub struct Root<K, V> {
node: BoxedNode<K, V>,
/// The number of levels below the root node.
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> {}
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 {
self.as_ref().is_shared_root()
}
/// Returns a shared tree, wrapping a shared root node that is eternally empty.
pub fn shared_empty_root() -> Self {
Root {
node: unsafe {
BoxedNode::from_ptr(NonNull::new_unchecked(
&EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _,
))
},
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
height: 0,
}
}
/// Returns a new owned tree, with its own root node that is initially empty.
pub fn new_leaf() -> Self {
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
}
@ -310,6 +314,7 @@ impl<K, V> Root<K, V> {
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
/// Turning this into a `NodeHeader` reference is always safe.
pub struct NodeRef<BorrowType, K, V, Type> {
/// The number of levels below the node.
height: usize,
node: NonNull<LeafNode<K, V>>,
// `root` is null unless the borrow type is `Mut`

View File

@ -264,8 +264,18 @@ pub struct ArgumentV1<'a> {
// could have been miscompiled. In practice, we never call as_usize on non-usize
// containing data (as a matter of static generation of the formatting
// arguments), so this is merely an additional check.
//
// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
// an address corresponding *only* to functions that also take `&usize` as their
// first argument. The read_volatile here ensures that we can safely ready out a
// usize from the passed reference and that this address does not point at a
// non-usize taking function.
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {};
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
// SAFETY: ptr is a reference
let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
loop {}
};
impl<'a> ArgumentV1<'a> {
#[doc(hidden)]

View File

@ -1,4 +1,6 @@
You tried to implement methods for a primitive type. Erroneous code example:
A method was implemented on a primitive type.
Erroneous code example:
```compile_fail,E0390
struct Foo {

View File

@ -306,23 +306,127 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
Ok(())
}
fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
/// Check a reference or `Box`.
fn check_safe_pointer(
&mut self,
value: OpTy<'tcx, M::PointerTag>,
kind: &str,
) -> InterpResult<'tcx> {
let value = self.ecx.read_immediate(value)?;
// Handle wide pointers.
// Check metadata early, for better diagnostics
let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
}
// Make sure this is dereferenceable and all.
let (size, align) = self
.ecx
.size_and_align_of(place.meta, place.layout)?
// for the purpose of validity, consider foreign types to have
// alignment and size determined by the layout (size will be 0,
// alignment should take attributes into account).
.unwrap_or_else(|| (place.layout.size, place.layout.align.abi));
let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align(
place.ptr,
size,
Some(align),
CheckInAllocMsg::InboundsTest,
) {
Ok(ptr) => ptr,
Err(err) => {
info!(
"{:?} did not pass access check for size {:?}, align {:?}",
place.ptr, size, align
);
match err.kind {
err_unsup!(InvalidNullPointerUsage) => {
throw_validation_failure!(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
let ty = value.layout.ty;
match ty.kind {
ty::Bool => {
let value = value.to_scalar_or_undef();
let value = self.ecx.read_scalar(value)?;
try_validation!(value.to_bool(), value, self.path, "a boolean");
Ok(true)
}
ty::Char => {
let value = value.to_scalar_or_undef();
let value = self.ecx.read_scalar(value)?;
try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint");
Ok(true)
}
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
let value = self.ecx.read_scalar(value)?;
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
let value = value.to_scalar_or_undef();
if self.ref_tracking_for_consts.is_some() {
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
@ -337,108 +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
// undef. We should fix that, but let's start low.
}
Ok(true)
}
ty::RawPtr(..) => {
// We are conservative with undef for integers, but try to
// actually enforce our current rules for raw pointers.
let place =
try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
let place = try_validation!(
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
"undefined pointer",
self.path
);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
}
Ok(true)
}
_ if ty.is_box() || ty.is_region_ptr() => {
// Handle wide pointers.
// Check metadata early, for better diagnostics
let place =
try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta, place.layout)?;
}
// Make sure this is dereferenceable and all.
let (size, align) = self
.ecx
.size_and_align_of(place.meta, place.layout)?
// for the purpose of validity, consider foreign types to have
// alignment and size determined by the layout (size will be 0,
// alignment should take attributes into account).
.unwrap_or_else(|| (place.layout.size, place.layout.align.abi));
let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align(
place.ptr,
size,
Some(align),
CheckInAllocMsg::InboundsTest,
) {
Ok(ptr) => ptr,
Err(err) => {
info!(
"{:?} did not pass access check for size {:?}, align {:?}",
place.ptr, size, align
);
match err.kind {
err_unsup!(InvalidNullPointerUsage) => {
throw_validation_failure!("a NULL reference", self.path)
}
err_unsup!(AlignmentCheckFailed { required, has }) => {
throw_validation_failure!(
format_args!(
"an unaligned reference \
(required {} byte alignment but found {})",
required.bytes(),
has.bytes()
),
self.path
)
}
err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(
"a dangling reference (created from integer)",
self.path
),
_ => throw_validation_failure!(
"a dangling reference (not entirely in bounds)",
self.path
),
}
}
};
// Recursive checking
if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts {
if let Some(ptr) = ptr {
// not a ZST
// Skip validation entirely for some external statics
let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
// `extern static` cannot be validated as they have no body.
// FIXME: Statics from other crates are also skipped.
// They might be checked at a different type, but for now we
// want to avoid recursing too deeply. This is not sound!
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
return Ok(());
}
}
}
// Proceed recursively even for ZST, no reason to skip them!
// `!` is a ZST and we want to validate it.
// Normalize before handing `place` to tracking because that will
// check for duplicates.
let place = if size.bytes() > 0 {
self.ecx.force_mplace_ptr(place).expect("we already bounds-checked")
} else {
place
};
let path = &self.path;
ref_tracking.track(place, || {
// We need to clone the path anyway, make sure it gets created
// with enough space for the additional `Deref`.
let mut new_path = Vec::with_capacity(path.len() + 1);
new_path.clone_from(path);
new_path.push(PathElem::Deref);
new_path
});
}
ty::Ref(..) => {
self.check_safe_pointer(value, "reference")?;
Ok(true)
}
ty::Adt(def, ..) if def.is_box() => {
self.check_safe_pointer(value, "box")?;
Ok(true)
}
ty::FnPtr(_sig) => {
let value = value.to_scalar_or_undef();
let value = self.ecx.read_scalar(value)?;
let _fn = try_validation!(
value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
value,
@ -446,11 +473,36 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
"a function pointer"
);
// FIXME: Check if the signature matches
Ok(true)
}
// This should be all the (inhabited) primitive types
_ => bug!("Unexpected primitive type {}", value.layout.ty),
ty::Never => throw_validation_failure!("a value of the never type `!`", self.path),
ty::Foreign(..) | ty::FnDef(..) => {
// Nothing to check.
Ok(true)
}
// 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(
@ -558,11 +610,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
}
#[inline(always)]
fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> {
// Empty unions are not accepted by rustc. That's great, it means we can
// use that as a signal for detecting primitives. Make sure
// we did not miss any primitive.
assert!(fields > 0);
fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> {
// Empty unions are not accepted by rustc. But uninhabited enums
// claim to be unions, so allow them, too.
assert!(op.layout.abi.is_uninhabited() || fields > 0);
Ok(())
}
@ -570,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> {
trace!("visit_value: {:?}, {:?}", *op, op.layout);
if op.layout.abi.is_uninhabited() {
// Uninhabited types do not have sensible layout, stop right here.
throw_validation_failure!(
format_args!("a value of uninhabited type {:?}", op.layout.ty),
self.path
)
}
// Check primitive types. We do this after checking for uninhabited types,
// to exclude 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);
// Check primitive types -- the leafs of our recursive descend.
if self.try_visit_primitive(op)? {
return Ok(());
}
// Sanity check: `builtin_deref` does not know any pointers that are not primitive.
assert!(op.layout.ty.builtin_deref(true).is_none());
// Recursively walk the type. Translate some possible errors to something nicer.
match self.walk_value(op) {
@ -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
// MyNewtype and then the scalar in there).
match op.layout.abi {
layout::Abi::Uninhabited => unreachable!(), // checked above
layout::Abi::Uninhabited => {
throw_validation_failure!(
format_args!("a value of uninhabited type {:?}", op.layout.ty),
self.path
);
}
layout::Abi::Scalar(ref scalar_layout) => {
self.visit_scalar(op, scalar_layout)?;
}

View File

@ -872,7 +872,7 @@ impl Niche {
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct LayoutDetails {
/// Says where the fields are located within the layout.
/// Primitives and fieldless enums appear as unions without fields.
/// Primitives and uninhabited enums appear as unions without fields.
pub fields: FieldPlacement,
/// Encodes information about multi-variant layouts.

View File

@ -459,12 +459,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ProbeScope::TraitsInScope,
)?;
debug!("resolve_ufcs: pick={:?}", pick);
for import_id in pick.import_ids {
let import_def_id = tcx.hir().local_def_id(import_id);
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
.unwrap()
.insert(import_def_id);
{
let mut tables = self.tables.borrow_mut();
let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap();
for import_id in pick.import_ids {
let import_def_id = tcx.hir().local_def_id(import_id);
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
used_trait_imports.insert(import_def_id);
}
}
let def_kind = pick.item.def_kind();

View File

@ -572,7 +572,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
fn assemble_inherent_candidates(&mut self) {
let steps = self.steps.clone();
let steps = Lrc::clone(&self.steps);
for step in steps.iter() {
self.assemble_probe(&step.self_ty);
}
@ -635,87 +635,51 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Slice(_) => {
let lang_def_id = lang_items.slice_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.slice_u8_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.slice_alloc_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.slice_u8_alloc_impl();
for &lang_def_id in &[
lang_items.slice_impl(),
lang_items.slice_u8_impl(),
lang_items.slice_alloc_impl(),
lang_items.slice_u8_alloc_impl(),
] {
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
}
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => {
let lang_def_id = match mutbl {
hir::Mutability::Not => lang_items.const_ptr_impl(),
hir::Mutability::Mut => lang_items.mut_ptr_impl(),
};
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
let lang_def_id = lang_items.const_ptr_impl();
ty::Int(i) => {
let lang_def_id = match i {
ast::IntTy::I8 => lang_items.i8_impl(),
ast::IntTy::I16 => lang_items.i16_impl(),
ast::IntTy::I32 => lang_items.i32_impl(),
ast::IntTy::I64 => lang_items.i64_impl(),
ast::IntTy::I128 => lang_items.i128_impl(),
ast::IntTy::Isize => lang_items.isize_impl(),
};
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
let lang_def_id = lang_items.mut_ptr_impl();
ty::Uint(i) => {
let lang_def_id = match i {
ast::UintTy::U8 => lang_items.u8_impl(),
ast::UintTy::U16 => lang_items.u16_impl(),
ast::UintTy::U32 => lang_items.u32_impl(),
ast::UintTy::U64 => lang_items.u64_impl(),
ast::UintTy::U128 => lang_items.u128_impl(),
ast::UintTy::Usize => lang_items.usize_impl(),
};
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::I8) => {
let lang_def_id = lang_items.i8_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::I16) => {
let lang_def_id = lang_items.i16_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::I32) => {
let lang_def_id = lang_items.i32_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::I64) => {
let lang_def_id = lang_items.i64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::I128) => {
let lang_def_id = lang_items.i128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Int(ast::IntTy::Isize) => {
let lang_def_id = lang_items.isize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::U8) => {
let lang_def_id = lang_items.u8_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::U16) => {
let lang_def_id = lang_items.u16_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::U32) => {
let lang_def_id = lang_items.u32_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::U64) => {
let lang_def_id = lang_items.u64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::U128) => {
let lang_def_id = lang_items.u128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Uint(ast::UintTy::Usize) => {
let lang_def_id = lang_items.usize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Float(ast::FloatTy::F32) => {
let lang_def_id = lang_items.f32_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.f32_runtime_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Float(ast::FloatTy::F64) => {
let lang_def_id = lang_items.f64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
let lang_def_id = lang_items.f64_runtime_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
ty::Float(f) => {
let (lang_def_id1, lang_def_id2) = match f {
ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()),
ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()),
};
self.assemble_inherent_impl_for_primitive(lang_def_id1);
self.assemble_inherent_impl_for_primitive(lang_def_id2);
}
_ => {}
}

View File

@ -407,7 +407,7 @@ impl File {
///
/// It is equivalent to `OpenOptions::new()` but allows you to write more
/// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
/// you can write `File::with_options().read(true).open("foo.txt"). This
/// you can write `File::with_options().read(true).open("foo.txt")`. This
/// also avoids the need to import `OpenOptions`.
///
/// See the [`OpenOptions::new`] function for more details.

View File

@ -1,34 +1,36 @@
#![feature(const_transmute, never_type)]
#![allow(const_err)] // make sure we cannot allow away the errors tested here
use std::mem;
#[repr(transparent)]
#[derive(Copy, Clone)]
struct Wrap<T>(T);
#[derive(Copy, Clone)]
enum Never {}
// # simple enum with discriminant 0
#[repr(usize)]
#[derive(Copy, Clone)]
enum Enum {
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
const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
//~^ ERROR is undefined behavior
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
//~^ ERROR is undefined behavior
// # simple enum with discriminant 2
// (Potentially) invalid enum discriminant
#[repr(usize)]
#[derive(Copy, Clone)]
@ -36,39 +38,58 @@ enum Enum2 {
A = 2,
}
#[repr(C)]
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 };
const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
//~^ ERROR is undefined behavior
const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
//~^ ERROR is undefined behavior
const BAD_ENUM2_WRAPPED: Wrap<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
// 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
// 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
// # valid discriminant for uninhabited variant
// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do*
// have a discriminant.
enum UninhDiscriminant {
A,
B(!),
C,
D(Never),
}
const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A
const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C
const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
//~^ ERROR is undefined behavior
const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
//~^ ERROR is undefined behavior
// # other
// Invalid enum field content (mostly to test printing of paths for enum tuple
// variants and tuples).
#[repr(C)]
union TransmuteChar {
a: u32,
b: char,
}
// Need to create something which does not clash with enum layout optimizations.
const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
//~^ ERROR is undefined behavior
// 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
fn main() {

View File

@ -1,75 +1,107 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
|
LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:26:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:29:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:48:1
--> $DIR/ub-enum.rs:41:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:50:1
--> $DIR/ub-enum.rs:43:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:52:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0.<enum-tag>, but expected initialized plain (non-pointer) bytes
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:56:1
--> $DIR/ub-enum.rs:55:1
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { 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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:60:1
--> $DIR/ub-enum.rs:59:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<enum-tag>, but expected initialized plain (non-pointer) bytes
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:71:1
--> $DIR/ub-enum.rs:76:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<enum-variant(Some)>.0.1, but expected a valid unicode codepoint
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
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`.

View File

@ -25,11 +25,11 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
//~^ ERROR it is undefined behavior to use this value
#[repr(C)]
union Transmute {
union MaybeUninit<T: Copy> {
uninit: (),
out: NonZeroU8,
init: T,
}
const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
//~^ ERROR it is undefined behavior to use this value
// Also test other uses of rustc_layout_scalar_valid_range_start

View File

@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:32:1
|
LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

View File

@ -8,9 +8,16 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
//~^ ERROR it is undefined behavior to use this value
//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
const UNALIGNED_BOX: Box<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) };
//~^ 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)`,
// but that would fail to compile; so we ended up breaking user code that would
// have worked fine had we not promoted.
@ -20,7 +27,13 @@ const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
//~^ ERROR it is undefined behavior to use this value
const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
//~^ ERROR it is undefined behavior to use this value
const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
//~^ ERROR it is undefined behavior to use this value
const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
//~^ ERROR it is undefined behavior to use this value
fn main() {}

View File

@ -9,13 +9,29 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:11:1
|
LL | const UNALIGNED_BOX: Box<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) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:17:1
--> $DIR/ub-ref.rs:18:1
|
LL | const NULL_BOX: Box<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) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
@ -23,7 +39,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:20:1
--> $DIR/ub-ref.rs:27:1
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<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.
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) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error: aborting due to 5 previous errors
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:36:1
|
LL | const USIZE_AS_BOX: Box<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`.

View File

@ -7,18 +7,18 @@ use std::mem;
enum Bar {}
#[repr(C)]
union TransmuteUnion<A: Clone + Copy, B: Clone + Copy> {
a: A,
b: B,
union MaybeUninit<T: Copy> {
uninit: (),
init: T,
}
const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
//~^ ERROR it is undefined behavior to use this value
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
//~^ ERROR it is undefined behavior to use this value
const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
//~^ ERROR it is undefined behavior to use this value
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-uninhabit.rs:15:1
|
LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
@ -17,8 +17,8 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-uninhabit.rs:21:1
|
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Bar; 1]
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

View File

@ -1,72 +1,18 @@
// ignore-tidy-linelength
#![feature(const_transmute)]
#![allow(unused)]
#![allow(const_err)] // make sure we cannot allow away the errors tested here
use std::mem;
// normalize-stderr-test "offset \d+" -> "offset N"
// normalize-stderr-test "allocation \d+" -> "allocation N"
// normalize-stderr-test "size \d+" -> "size N"
#[repr(C)]
union BoolTransmute {
val: u8,
bl: bool,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct SliceRepr {
ptr: *const u8,
len: usize,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct BadSliceRepr {
ptr: *const u8,
len: &'static u8,
}
#[repr(C)]
union SliceTransmute {
repr: SliceRepr,
bad: BadSliceRepr,
addr: usize,
slice: &'static [u8],
raw_slice: *const [u8],
str: &'static str,
my_str: &'static MyStr,
my_slice: &'static MySliceBool,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct DynRepr {
ptr: *const u8,
vtable: *const u8,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct DynRepr2 {
ptr: *const u8,
vtable: *const u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct BadDynRepr {
ptr: *const u8,
vtable: usize,
}
#[repr(C)]
union DynTransmute {
repr: DynRepr,
repr2: DynRepr2,
bad: BadDynRepr,
addr: usize,
rust: &'static dyn Trait,
raw_rust: *const dyn Trait,
union MaybeUninit<T: Copy> {
uninit: (),
init: T,
}
trait Trait {}
@ -81,90 +27,99 @@ type MySliceBool = MySlice<[bool]>;
// # str
// OK
const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) };
// bad str
const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR it is undefined behavior to use this value
// bad str
const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
//~^ ERROR it is undefined behavior to use this value
// bad str in user-defined unsized type
const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
//~^ ERROR it is undefined behavior to use this value
// invalid UTF-8
const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
//~^ ERROR it is undefined behavior to use this value
// invalid UTF-8 in user-defined str-like
const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) };
//~^ ERROR it is undefined behavior to use this value
// # slice
// OK
const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) };
// bad slice: length uninit
const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
//~^ ERROR it is undefined behavior to use this value
let uninit_len = MaybeUninit::<usize> { uninit: () };
mem::transmute((42, uninit_len))
};
// bad slice: length too big
const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR it is undefined behavior to use this value
// bad slice: length not an int
const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
//~^ ERROR it is undefined behavior to use this value
// bad slice box: length too big
const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR it is undefined behavior to use this value
// bad slice box: length not an int
const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
//~^ ERROR it is undefined behavior to use this value
// bad data *inside* the slice
const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
//~^ ERROR it is undefined behavior to use this value
// good MySliceBool
const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
// bad: sized field is not okay
const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]);
const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
//~^ ERROR it is undefined behavior to use this value
// bad: unsized part is not okay
const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
//~^ ERROR it is undefined behavior to use this value
// # raw slice
const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw
const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw
const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
//~^ ERROR it is undefined behavior to use this value
let uninit_len = MaybeUninit::<usize> { uninit: () };
mem::transmute((42, uninit_len))
};
// # trait object
// bad trait object
const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
//~^ ERROR it is undefined behavior to use this value
// bad trait object
const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
//~^ ERROR it is undefined behavior to use this value
// bad trait object
const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
//~^ ERROR it is undefined behavior to use this value
// bad data *inside* the trait object
const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
//~^ ERROR it is undefined behavior to use this value
// # raw trait object
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust};
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
//~^ ERROR it is undefined behavior to use this value
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
//~^ ERROR it is undefined behavior to use this value
const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw
const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw
// Const eval fails for these, so they need to be statics to error.
static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
//~^ ERROR could not evaluate static initializer
};
static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
//~^ ERROR could not evaluate static initializer
};
fn main() {
let _ = RAW_TRAIT_OBJ_VTABLE_NULL;
let _ = RAW_TRAIT_OBJ_VTABLE_INVALID;
}
fn main() {}

View File

@ -1,159 +1,183 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:86:1
--> $DIR/ub-wide-ptr.rs:32:1
|
LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:89:1
--> $DIR/ub-wide-ptr.rs:35:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs: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};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:96:1
--> $DIR/ub-wide-ptr.rs:42:1
|
LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>
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>
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:99:1
--> $DIR/ub-wide-ptr.rs:45:1
|
LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at .<deref>.0
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
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:106:1
--> $DIR/ub-wide-ptr.rs:52:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer
LL | / const SLICE_LENGTH_UNINIT: &[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: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.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:109:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds)
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:112:1
--> $DIR/ub-wide-ptr.rs:111:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:116:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<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
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
error[E0080]: could not evaluate static initializer
--> $DIR/ub-wide-ptr.rs:159:5
--> $DIR/ub-wide-ptr.rs:117:5
|
LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer
error[E0080]: could not evaluate static initializer
--> $DIR/ub-wide-ptr.rs:163:5
--> $DIR/ub-wide-ptr.rs:121:5
|
LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N
error: aborting due to 20 previous errors
error: aborting due to 22 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_uninhabited_zsts.rs:17:1
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Empty; 3]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0]
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.

View File

@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_never_arrays.rs:3:1
|
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at .<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.
@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_never_arrays.rs:6:1
|
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .<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.
@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_never_arrays.rs:7:1
|
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .<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.