Skip to content

Commit

Permalink
allow numbers with provenance within CTFE execution
Browse files Browse the repository at this point in the history
This effectively reverts rust-lang#97684 for CTFE
  • Loading branch information
RalfJung committed Jul 30, 2022
1 parent 12c5b1e commit 29ce4d5
Show file tree
Hide file tree
Showing 18 changed files with 366 additions and 467 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {

#[inline(always)]
fn enforce_number_no_provenance(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
true
false
}

#[inline(always)]
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
{ "{:x}", value } expected { "initialized bytes" }
);
}
if M::enforce_number_no_provenance(self.ecx) {
// Always check for number provenance during CTFE validation, even if the machine
// internally temporarily accepts number provenance.
if self.ctfe_mode.is_some() || M::enforce_number_no_provenance(self.ecx) {
// As a special exception we *do* match on a `Scalar` here, since we truly want
// to know its underlying representation (and *not* cast it to an integer).
let is_ptr = value.check_init().map_or(false, |v| matches!(v, Scalar::Ptr(..)));
Expand Down Expand Up @@ -924,10 +926,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
return Ok(());
};

// Always check for number provenance during CTFE validation, even if the machine
// internally temporarily accepts number provenance.
match alloc.check_bytes(
alloc_range(Size::ZERO, size),
/*allow_uninit*/ !M::enforce_number_init(self.ecx),
/*allow_ptr*/ !M::enforce_number_no_provenance(self.ecx),
/*allow_ptr*/ !(self.ctfe_mode.is_some() || M::enforce_number_no_provenance(self.ecx)),
) {
// In the happy case, we needn't check anything else.
Ok(()) => {}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ union Nonsense {

fn main() {
const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
//~^ ERROR any use of this value will cause an error
Expand All @@ -40,8 +39,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
//~^ ERROR it is undefined behavior to use this value
Expand All @@ -59,8 +57,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
//~^ ERROR it is undefined behavior to use this value
Expand All @@ -70,8 +67,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
//~^ ERROR any use of this value will cause an error
Expand All @@ -94,8 +90,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
//~^ ERROR any use of this value will cause an error
Expand All @@ -114,8 +109,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
//~^ ERROR any use of this value will cause an error
Expand All @@ -126,8 +120,7 @@ fn main() {
//~| WARN this was previously accepted by the compiler but is being phased out

const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
//~^ ERROR it is undefined behavior to use this value

const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
//~^ ERROR any use of this value will cause an error
Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
error: any use of this value will cause an error
--> $DIR/ref_to_int_match.rs:25:27
error[E0080]: it is undefined behavior to use this value
--> $DIR/ref_to_int_match.rs:25:1
|
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
| --------------------------^^^^^^^^^^^^^^^^---
| |
| unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected plain (non-pointer) bytes
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc3──╼ │ ╾──╼
}

error: could not evaluate constant pattern
--> $DIR/ref_to_int_match.rs:7:14
Expand All @@ -24,3 +23,4 @@ LL | 10..=BAR => {},

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0080`.
16 changes: 8 additions & 8 deletions src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
error: any use of this value will cause an error
--> $DIR/ref_to_int_match.rs:25:27
error[E0080]: it is undefined behavior to use this value
--> $DIR/ref_to_int_match.rs:25:1
|
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
| --------------------------^^^^^^^^^^^^^^^^---
| |
| unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected plain (non-pointer) bytes
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
╾───────alloc3────────╼ │ ╾──────╼
}

error: could not evaluate constant pattern
--> $DIR/ref_to_int_match.rs:7:14
Expand All @@ -24,3 +23,4 @@ LL | 10..=BAR => {},

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0080`.
4 changes: 1 addition & 3 deletions src/test/ui/consts/const-eval/ref_to_int_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,4 @@ type Int = u64;
#[cfg(target_pointer_width="32")]
type Int = u32;

const BAR: Int = unsafe { Foo { r: &42 }.f };
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value
75 changes: 42 additions & 33 deletions src/test/ui/consts/const-eval/ub-enum.32bit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
--> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
Expand All @@ -9,27 +9,30 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
01 00 00 00 │ ....
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc9, but expected plain (non-pointer) bytes
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc9──╼ │ ╾──╼
}

error: any use of this value will cause an error
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:30:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc13, but expected plain (non-pointer) bytes
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc13─╼ │ ╾──╼
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:43:1
--> $DIR/ub-enum.rs:42:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
Expand All @@ -39,26 +42,30 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
00 00 00 00 │ ....
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc19, but expected plain (non-pointer) bytes
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc19─╼ │ ╾──╼
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:47:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc23, but expected plain (non-pointer) bytes
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc23─╼ │ ╾──╼
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:59:1
--> $DIR/ub-enum.rs:56:1
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered uninitialized bytes, but expected initialized bytes
Expand All @@ -68,17 +75,19 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
__ __ __ __ │ ░░░░
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:63:1
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:60:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc30, but expected plain (non-pointer) bytes
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
╾─alloc30─╼ │ ╾──╼
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:81:1
--> $DIR/ub-enum.rs:77:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(B)>.0: encountered a value of the never type `!`
Expand All @@ -89,7 +98,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:83:1
--> $DIR/ub-enum.rs:79:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
Expand All @@ -100,7 +109,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:91:1
--> $DIR/ub-enum.rs:87:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
Expand All @@ -111,13 +120,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:96:77
--> $DIR/ub-enum.rs:92:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:98:77
--> $DIR/ub-enum.rs:94:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
Expand Down

0 comments on commit 29ce4d5

Please sign in to comment.