Skip to content

Commit 729f4cd

Browse files
committed
we cannot short-circuit just becuase the Abi seems harmless
also add tests for ScalarPair enums
1 parent 6e66f58 commit 729f4cd

File tree

2 files changed

+59
-52
lines changed

2 files changed

+59
-52
lines changed

src/librustc_target/abi/mod.rs

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ impl<'a, Ty> TyLayout<'a, Ty> {
10451045
/// This is conservative: in doubt, it will answer `true`.
10461046
///
10471047
/// FIXME: Once we removed all the conservatism, we could alternatively
1048-
/// create an all-0/all-undef constant and run the vonst value validator to see if
1048+
/// create an all-0/all-undef constant and run the const value validator to see if
10491049
/// this is a valid value for the given type.
10501050
pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
10511051
where
@@ -1067,59 +1067,22 @@ impl<'a, Ty> TyLayout<'a, Ty> {
10671067
}
10681068
};
10691069

1070-
// Abi is the most informative here.
1071-
let res = match &self.abi {
1070+
// Check the ABI.
1071+
let valid = match &self.abi {
10721072
Abi::Uninhabited => false, // definitely UB
10731073
Abi::Scalar(s) => scalar_allows_raw_init(s),
10741074
Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
10751075
Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
1076-
Abi::Aggregate { .. } => {
1077-
match self.variants {
1078-
Variants::Multiple { .. } => {
1079-
if zero {
1080-
// FIXME(#66151):
1081-
// could we identify the variant with discriminant 0, check that?
1082-
true
1083-
} else {
1084-
// FIXME(#66151): This needs to have some sort of discriminant,
1085-
// which cannot be undef. But for now we are conservative.
1086-
true
1087-
}
1088-
}
1089-
Variants::Single { .. } => {
1090-
// For aggregates, recurse.
1091-
match self.fields {
1092-
FieldPlacement::Union(..) => true, // An all-0 unit is fine.
1093-
FieldPlacement::Array { .. } =>
1094-
// FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays
1095-
// with any element type, so let us not (yet) complain about that.
1096-
/* count == 0 ||
1097-
self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */
1098-
{
1099-
true
1100-
}
1101-
FieldPlacement::Arbitrary { .. } => {
1102-
// FIXME(#66151) cargo depends on sized-chunks 0.3.0 which
1103-
// has some illegal zero-initialization, so let us not (yet)
1104-
// complain about aggregates either.
1105-
/* let mut res = true;
1106-
// Check that all fields accept zero-init.
1107-
for idx in 0..offsets.len() {
1108-
let field = self.field(cx, idx).to_result()?;
1109-
if !field.might_permit_raw_init(cx, zero)? {
1110-
res = false;
1111-
break;
1112-
}
1113-
}
1114-
res */
1115-
true
1116-
}
1117-
}
1118-
}
1119-
}
1120-
}
1076+
Abi::Aggregate { .. } => true, // Cannot be excluded *right now*.
11211077
};
1122-
trace!("might_permit_raw_init({:?}, zero={}) = {}", self.details, zero, res);
1123-
Ok(res)
1078+
if !valid {
1079+
// This is definitely not okay.
1080+
trace!("might_permit_raw_init({:?}, zero={}): not valid", self.details, zero);
1081+
return Ok(false);
1082+
}
1083+
1084+
// If we have not found an error yet, we need to recursively descend.
1085+
// FIXME(#66151): For now, we are conservative and do not do this.
1086+
Ok(true)
11241087
}
11251088
}

src/test/ui/intrinsics/panic-uninitialized-zeroed.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
#![allow(deprecated, invalid_value)]
88

99
use std::{
10-
mem::{self, MaybeUninit},
10+
mem::{self, MaybeUninit, ManuallyDrop},
1111
panic,
1212
ptr::NonNull,
13+
num,
1314
};
1415

1516
#[allow(dead_code)]
@@ -23,6 +24,18 @@ enum Bar {}
2324
#[allow(dead_code)]
2425
enum OneVariant { Variant(i32) }
2526

27+
// An enum with ScalarPair layout
28+
#[allow(dead_code)]
29+
enum LR {
30+
Left(i64),
31+
Right(i64),
32+
}
33+
#[allow(dead_code, non_camel_case_types)]
34+
enum LR_NonZero {
35+
Left(num::NonZeroI64),
36+
Right(num::NonZeroI64),
37+
}
38+
2639
fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
2740
let err = panic::catch_unwind(op).err();
2841
assert_eq!(
@@ -33,7 +46,7 @@ fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
3346

3447
fn main() {
3548
unsafe {
36-
// Uninitialized types
49+
// Uninhabited types
3750
test_panic_msg(
3851
|| mem::uninitialized::<!>(),
3952
"attempted to instantiate uninhabited type `!`"
@@ -93,6 +106,26 @@ fn main() {
93106
);
94107

95108
/* FIXME(#66151) we conservatively do not error here yet.
109+
test_panic_msg(
110+
|| mem::uninitialized::<LR_NonZero>(),
111+
"attempted to leave type `LR_NonZero` uninitialized, which is invalid"
112+
);
113+
test_panic_msg(
114+
|| mem::zeroed::<LR_NonZero>(),
115+
"attempted to zero-initialize type `LR_NonZero`, which is invalid"
116+
);
117+
118+
test_panic_msg(
119+
|| mem::uninitialized::<ManuallyDrop<LR_NonZero>>(),
120+
"attempted to leave type `std::mem::ManuallyDrop<LR_NonZero>` uninitialized, \
121+
which is invalid"
122+
);
123+
test_panic_msg(
124+
|| mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
125+
"attempted to zero-initialize type `std::mem::ManuallyDrop<LR_NonZero>`, \
126+
which is invalid"
127+
);
128+
96129
test_panic_msg(
97130
|| mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
98131
"attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
@@ -105,13 +138,24 @@ fn main() {
105138
);
106139
*/
107140

141+
// Types that can be zero, but not uninit.
108142
test_panic_msg(
109143
|| mem::uninitialized::<bool>(),
110144
"attempted to leave type `bool` uninitialized, which is invalid"
111145
);
146+
test_panic_msg(
147+
|| mem::uninitialized::<LR>(),
148+
"attempted to leave type `LR` uninitialized, which is invalid"
149+
);
150+
test_panic_msg(
151+
|| mem::uninitialized::<ManuallyDrop<LR>>(),
152+
"attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid"
153+
);
112154

113155
// Some things that should work.
114156
let _val = mem::zeroed::<bool>();
157+
let _val = mem::zeroed::<LR>();
158+
let _val = mem::zeroed::<ManuallyDrop<LR>>();
115159
let _val = mem::zeroed::<OneVariant>();
116160
let _val = mem::zeroed::<Option<&'static i32>>();
117161
let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();

0 commit comments

Comments
 (0)