This commit is contained in:
Ralf Jung 2020-02-16 22:45:28 +01:00
parent b133d6776f
commit 6e66f586a0
3 changed files with 28 additions and 29 deletions

View File

@ -524,13 +524,17 @@ fn codegen_call_terminator(
// These are intrinsics that compile to panics so that we can get a message
// which mentions the offending type, even from a const context.
#[derive(Debug, PartialEq)]
enum PanicIntrinsic { IfUninhabited, IfZeroInvalid, IfAnyInvalid };
enum PanicIntrinsic {
IfUninhabited,
IfZeroInvalid,
IfAnyInvalid,
};
let panic_intrinsic = intrinsic.and_then(|i| match i {
// FIXME: Move to symbols instead of strings.
"panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited),
"panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid),
"panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid),
_ => None
_ => None,
});
if let Some(intrinsic) = panic_intrinsic {
use PanicIntrinsic::*;
@ -538,10 +542,10 @@ fn codegen_call_terminator(
let layout = bx.layout_of(ty);
let do_panic = match intrinsic {
IfUninhabited => layout.abi.is_uninhabited(),
IfZeroInvalid => // We unwrap as the error type is `!`.
!layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(),
IfAnyInvalid => // We unwrap as the error type is `!`.
!layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(),
// We unwrap as the error type is `!`.
IfZeroInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(),
// We unwrap as the error type is `!`.
IfAnyInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(),
};
if do_panic {
let msg_str = if layout.abi.is_uninhabited() {

View File

@ -1047,22 +1047,17 @@ pub fn is_zst(&self) -> bool {
/// 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
/// 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>
pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
where
Self: Copy,
Ty: TyLayoutMethods<'a, C>,
C: LayoutOf<Ty = Ty, TyLayout: MaybeResult<Self, Error = E>> + HasDataLayout
C: LayoutOf<Ty = Ty, TyLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
{
let scalar_allows_raw_init = move |s: &Scalar| -> bool {
if zero {
let range = &s.valid_range;
// The range must contain 0.
range.contains(&0) ||
(*range.start() > *range.end()) // wrap-around allows 0
range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0
} else {
// The range must include all values. `valid_range_exclusive` handles
// the wrap-around using target arithmetic; with wrap-around then the full
@ -1076,13 +1071,11 @@ pub fn might_permit_raw_init<C, E>(
let res = 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::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 { .. } =>
Variants::Multiple { .. } => {
if zero {
// FIXME(#66151):
// could we identify the variant with discriminant 0, check that?
@ -1091,17 +1084,20 @@ pub fn might_permit_raw_init<C, E>(
// 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,
// 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)

View File

@ -147,10 +147,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
),
"rustc_peek" => (1, vec![param(0)], param(0)),
"caller_location" => (0, vec![], tcx.caller_location_ty()),
"panic_if_uninhabited" |
"panic_if_zero_invalid" |
"panic_if_any_invalid" =>
(1, Vec::new(), tcx.mk_unit()),
"panic_if_uninhabited" | "panic_if_zero_invalid" | "panic_if_any_invalid" => {
(1, Vec::new(), tcx.mk_unit())
}
"init" => (1, Vec::new(), param(0)),
"uninit" => (1, Vec::new(), param(0)),
"forget" => (1, vec![param(0)], tcx.mk_unit()),