Skip to content

Commit 7410ebb

Browse files
committed
Auto merge of rust-lang#99965 - RalfJung:ctfe-number-prov, r=eddyb
allow numbers with provenance within CTFE execution This effectively reverts rust-lang#97684 for CTFE. Undoes the diagnostic changes that are tracked in rust-lang#99923, only for beta. (On master this patch wouldn't apply any more, `enforce_number_no_provenance` is gone with rust-lang#99644 since the interpreter engine is not supposed to ever have provenance on integers.) The test changes are an exact un-do of rust-lang#97684. However there is still some risk here since this exact code is not what has been battle-tested. r? `@Mark-Simulacrum`
2 parents 12c5b1e + 29ce4d5 commit 7410ebb

18 files changed

+366
-467
lines changed

compiler/rustc_const_eval/src/interpret/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
465465

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

471471
#[inline(always)]

compiler/rustc_const_eval/src/interpret/validity.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
552552
{ "{:x}", value } expected { "initialized bytes" }
553553
);
554554
}
555-
if M::enforce_number_no_provenance(self.ecx) {
555+
// Always check for number provenance during CTFE validation, even if the machine
556+
// internally temporarily accepts number provenance.
557+
if self.ctfe_mode.is_some() || M::enforce_number_no_provenance(self.ecx) {
556558
// As a special exception we *do* match on a `Scalar` here, since we truly want
557559
// to know its underlying representation (and *not* cast it to an integer).
558560
let is_ptr = value.check_init().map_or(false, |v| matches!(v, Scalar::Ptr(..)));
@@ -924,10 +926,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
924926
return Ok(());
925927
};
926928

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

src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr

+72-72
Large diffs are not rendered by default.

src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ union Nonsense {
2424

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

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

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

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

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

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

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

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

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

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

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

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

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

132125
const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
133126
//~^ ERROR any use of this value will cause an error
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
error: any use of this value will cause an error
2-
--> $DIR/ref_to_int_match.rs:25:27
1+
error[E0080]: it is undefined behavior to use this value
2+
--> $DIR/ref_to_int_match.rs:25:1
33
|
44
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
5-
| --------------------------^^^^^^^^^^^^^^^^---
6-
| |
7-
| unable to turn pointer into raw bytes
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected plain (non-pointer) bytes
86
|
9-
= note: `#[deny(const_err)]` on by default
10-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
11-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
7+
= 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.
8+
= note: the raw bytes of the constant (size: 4, align: 4) {
9+
╾─alloc3──╼ │ ╾──╼
10+
}
1211

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

2524
error: aborting due to 3 previous errors
2625

26+
For more information about this error, try `rustc --explain E0080`.
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
error: any use of this value will cause an error
2-
--> $DIR/ref_to_int_match.rs:25:27
1+
error[E0080]: it is undefined behavior to use this value
2+
--> $DIR/ref_to_int_match.rs:25:1
33
|
44
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
5-
| --------------------------^^^^^^^^^^^^^^^^---
6-
| |
7-
| unable to turn pointer into raw bytes
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected plain (non-pointer) bytes
86
|
9-
= note: `#[deny(const_err)]` on by default
10-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
11-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
7+
= 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.
8+
= note: the raw bytes of the constant (size: 8, align: 8) {
9+
╾───────alloc3────────╼ │ ╾──────╼
10+
}
1211

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

2524
error: aborting due to 3 previous errors
2625

26+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/ref_to_int_match.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,4 @@ type Int = u64;
2222
#[cfg(target_pointer_width="32")]
2323
type Int = u32;
2424

25-
const BAR: Int = unsafe { Foo { r: &42 }.f };
26-
//~^ ERROR any use of this value will cause an error
27-
//~| WARN this was previously accepted by the compiler but is being phased out
25+
const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value

src/test/ui/consts/const-eval/ub-enum.32bit.stderr

+42-33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0080]: it is undefined behavior to use this value
2-
--> $DIR/ub-enum.rs:23:1
2+
--> $DIR/ub-enum.rs:24:1
33
|
44
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
@@ -9,27 +9,30 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
99
01 00 00 00 │ ....
1010
}
1111

12-
error: any use of this value will cause an error
13-
--> $DIR/ub-enum.rs:26:1
12+
error[E0080]: it is undefined behavior to use this value
13+
--> $DIR/ub-enum.rs:27:1
1414
|
1515
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc9, but expected plain (non-pointer) bytes
1717
|
18-
= note: `#[deny(const_err)]` on by default
19-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
20-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
18+
= 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.
19+
= note: the raw bytes of the constant (size: 4, align: 4) {
20+
╾─alloc9──╼ │ ╾──╼
21+
}
2122

22-
error: any use of this value will cause an error
23+
error[E0080]: it is undefined behavior to use this value
2324
--> $DIR/ub-enum.rs:30:1
2425
|
2526
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc13, but expected plain (non-pointer) bytes
2728
|
28-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
29-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
29+
= 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.
30+
= note: the raw bytes of the constant (size: 4, align: 4) {
31+
╾─alloc13─╼ │ ╾──╼
32+
}
3033

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

42-
error: any use of this value will cause an error
43-
--> $DIR/ub-enum.rs:45:1
45+
error[E0080]: it is undefined behavior to use this value
46+
--> $DIR/ub-enum.rs:44:1
4447
|
4548
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc19, but expected plain (non-pointer) bytes
4750
|
48-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
49-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
51+
= 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.
52+
= note: the raw bytes of the constant (size: 4, align: 4) {
53+
╾─alloc19─╼ │ ╾──╼
54+
}
5055

51-
error: any use of this value will cause an error
52-
--> $DIR/ub-enum.rs:49:1
56+
error[E0080]: it is undefined behavior to use this value
57+
--> $DIR/ub-enum.rs:47:1
5358
|
5459
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
55-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
60+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.<enum-tag>: encountered pointer to alloc23, but expected plain (non-pointer) bytes
5661
|
57-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
58-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
62+
= 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.
63+
= note: the raw bytes of the constant (size: 4, align: 4) {
64+
╾─alloc23─╼ │ ╾──╼
65+
}
5966

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

71-
error: any use of this value will cause an error
72-
--> $DIR/ub-enum.rs:63:1
78+
error[E0080]: it is undefined behavior to use this value
79+
--> $DIR/ub-enum.rs:60:1
7380
|
7481
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
75-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
82+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-tag>: encountered pointer to alloc30, but expected plain (non-pointer) bytes
7683
|
77-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
78-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
84+
= 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.
85+
= note: the raw bytes of the constant (size: 4, align: 4) {
86+
╾─alloc30─╼ │ ╾──╼
87+
}
7988

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

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

102111
error[E0080]: it is undefined behavior to use this value
103-
--> $DIR/ub-enum.rs:91:1
112+
--> $DIR/ub-enum.rs:87:1
104113
|
105114
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
106115
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`)
@@ -111,13 +120,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
111120
}
112121

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

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

0 commit comments

Comments
 (0)