we cannot short-circuit just becuase the Abi seems harmless
also add tests for ScalarPair enums
This commit is contained in:
parent
6e66f586a0
commit
729f4cd9ae
@ -1045,7 +1045,7 @@ pub fn is_zst(&self) -> bool {
|
||||
/// This is conservative: in doubt, it will answer `true`.
|
||||
///
|
||||
/// FIXME: Once we removed all the conservatism, we could alternatively
|
||||
/// create an all-0/all-undef constant and run the vonst value validator to see if
|
||||
/// create an all-0/all-undef constant and run the const value validator to see if
|
||||
/// this is a valid value for the given type.
|
||||
pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
|
||||
where
|
||||
@ -1067,59 +1067,22 @@ pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
|
||||
}
|
||||
};
|
||||
|
||||
// Abi is the most informative here.
|
||||
let res = match &self.abi {
|
||||
// Check the ABI.
|
||||
let valid = match &self.abi {
|
||||
Abi::Uninhabited => false, // definitely UB
|
||||
Abi::Scalar(s) => scalar_allows_raw_init(s),
|
||||
Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
|
||||
Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
|
||||
Abi::Aggregate { .. } => {
|
||||
match self.variants {
|
||||
Variants::Multiple { .. } => {
|
||||
if zero {
|
||||
// FIXME(#66151):
|
||||
// could we identify the variant with discriminant 0, check that?
|
||||
true
|
||||
} else {
|
||||
// FIXME(#66151): This needs to have some sort of discriminant,
|
||||
// which cannot be undef. But for now we are conservative.
|
||||
true
|
||||
}
|
||||
}
|
||||
Variants::Single { .. } => {
|
||||
// For aggregates, recurse.
|
||||
match self.fields {
|
||||
FieldPlacement::Union(..) => true, // An all-0 unit is fine.
|
||||
FieldPlacement::Array { .. } =>
|
||||
// FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays
|
||||
// with any element type, so let us not (yet) complain about that.
|
||||
/* count == 0 ||
|
||||
self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */
|
||||
{
|
||||
true
|
||||
}
|
||||
FieldPlacement::Arbitrary { .. } => {
|
||||
// FIXME(#66151) cargo depends on sized-chunks 0.3.0 which
|
||||
// has some illegal zero-initialization, so let us not (yet)
|
||||
// complain about aggregates either.
|
||||
/* let mut res = true;
|
||||
// Check that all fields accept zero-init.
|
||||
for idx in 0..offsets.len() {
|
||||
let field = self.field(cx, idx).to_result()?;
|
||||
if !field.might_permit_raw_init(cx, zero)? {
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
res */
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Abi::Aggregate { .. } => true, // Cannot be excluded *right now*.
|
||||
};
|
||||
trace!("might_permit_raw_init({:?}, zero={}) = {}", self.details, zero, res);
|
||||
Ok(res)
|
||||
if !valid {
|
||||
// This is definitely not okay.
|
||||
trace!("might_permit_raw_init({:?}, zero={}): not valid", self.details, zero);
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// If we have not found an error yet, we need to recursively descend.
|
||||
// FIXME(#66151): For now, we are conservative and do not do this.
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,10 @@
|
||||
#![allow(deprecated, invalid_value)]
|
||||
|
||||
use std::{
|
||||
mem::{self, MaybeUninit},
|
||||
mem::{self, MaybeUninit, ManuallyDrop},
|
||||
panic,
|
||||
ptr::NonNull,
|
||||
num,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -23,6 +24,18 @@ enum Bar {}
|
||||
#[allow(dead_code)]
|
||||
enum OneVariant { Variant(i32) }
|
||||
|
||||
// An enum with ScalarPair layout
|
||||
#[allow(dead_code)]
|
||||
enum LR {
|
||||
Left(i64),
|
||||
Right(i64),
|
||||
}
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
enum LR_NonZero {
|
||||
Left(num::NonZeroI64),
|
||||
Right(num::NonZeroI64),
|
||||
}
|
||||
|
||||
fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
|
||||
let err = panic::catch_unwind(op).err();
|
||||
assert_eq!(
|
||||
@ -33,7 +46,7 @@ fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Uninitialized types
|
||||
// Uninhabited types
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<!>(),
|
||||
"attempted to instantiate uninhabited type `!`"
|
||||
@ -93,6 +106,26 @@ fn main() {
|
||||
);
|
||||
|
||||
/* FIXME(#66151) we conservatively do not error here yet.
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<LR_NonZero>(),
|
||||
"attempted to leave type `LR_NonZero` uninitialized, which is invalid"
|
||||
);
|
||||
test_panic_msg(
|
||||
|| mem::zeroed::<LR_NonZero>(),
|
||||
"attempted to zero-initialize type `LR_NonZero`, which is invalid"
|
||||
);
|
||||
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<ManuallyDrop<LR_NonZero>>(),
|
||||
"attempted to leave type `std::mem::ManuallyDrop<LR_NonZero>` uninitialized, \
|
||||
which is invalid"
|
||||
);
|
||||
test_panic_msg(
|
||||
|| mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
|
||||
"attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \
|
||||
which is invalid"
|
||||
);
|
||||
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
|
||||
"attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
|
||||
@ -105,13 +138,24 @@ fn main() {
|
||||
);
|
||||
*/
|
||||
|
||||
// Types that can be zero, but not uninit.
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<bool>(),
|
||||
"attempted to leave type `bool` uninitialized, which is invalid"
|
||||
);
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<LR>(),
|
||||
"attempted to leave type `LR` uninitialized, which is invalid"
|
||||
);
|
||||
test_panic_msg(
|
||||
|| mem::uninitialized::<ManuallyDrop<LR>>(),
|
||||
"attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid"
|
||||
);
|
||||
|
||||
// Some things that should work.
|
||||
let _val = mem::zeroed::<bool>();
|
||||
let _val = mem::zeroed::<LR>();
|
||||
let _val = mem::zeroed::<ManuallyDrop<LR>>();
|
||||
let _val = mem::zeroed::<OneVariant>();
|
||||
let _val = mem::zeroed::<Option<&'static i32>>();
|
||||
let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
|
||||
|
Loading…
Reference in New Issue
Block a user