Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow numbers with provenance within CTFE execution #99965

Merged
merged 1 commit into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Comment on lines 467 to +468
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this only read during "CTFE validation", before? Could self.ctfe_mode.is_some() calls be moved into here instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this only read during "CTFE validation", before?

Yes. #97684 made it also relevant for read_immediate.

Could self.ctfe_mode.is_some() calls be moved into here instead?

No; the self in validation is the validation visitor, and that has the ctfe_mode -- but that doesn't exist in read_immediate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess alternatively in this PR we could make enforce_number_no_provenance again only relevant for validation, and not for read_immediate. That would break Miri but we don't care about Miri on the beta branch.

}

#[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
Loading