Rollup merge of #85112 - RalfJung:promoted-errors, r=oli-obk
ensure failing promoteds in const/static bodies are handled correctly `const`/`static` bodies are the one case where we still promote code that might fail to evaluate. Ensure that this is handled correctly; in particular, it must not fail compilation. `src/test/ui/consts/const-eval/erroneous-const.rs` ensures that when a non-promoted fails to evaluate, we *do* show an error. r? `@oli-obk`
This commit is contained in:
commit
ae8a438034
8 changed files with 101 additions and 19 deletions
|
@ -10,6 +10,8 @@ impl<T> PrintName<T> {
|
||||||
|
|
||||||
const fn no_codegen<T>() {
|
const fn no_codegen<T>() {
|
||||||
if false {
|
if false {
|
||||||
|
// This bad constant is only used in dead code in a no-codegen function... and yet we still
|
||||||
|
// must make sure that the build fails.
|
||||||
let _ = PrintName::<T>::VOID; //~ERROR could not evaluate static initializer
|
let _ = PrintName::<T>::VOID; //~ERROR could not evaluate static initializer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,16 +27,16 @@ LL | #![warn(const_err, unconditional_panic)]
|
||||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
error[E0080]: could not evaluate static initializer
|
error[E0080]: could not evaluate static initializer
|
||||||
--> $DIR/erroneous-const.rs:13:17
|
--> $DIR/erroneous-const.rs:15:17
|
||||||
|
|
|
|
||||||
LL | let _ = PrintName::<T>::VOID;
|
LL | let _ = PrintName::<T>::VOID;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| referenced constant has errors
|
| referenced constant has errors
|
||||||
| inside `no_codegen::<i32>` at $DIR/erroneous-const.rs:13:17
|
| inside `no_codegen::<i32>` at $DIR/erroneous-const.rs:15:17
|
||||||
...
|
...
|
||||||
LL | pub static FOO: () = no_codegen::<i32>();
|
LL | pub static FOO: () = no_codegen::<i32>();
|
||||||
| ------------------- inside `FOO` at $DIR/erroneous-const.rs:17:22
|
| ------------------- inside `FOO` at $DIR/erroneous-const.rs:19:22
|
||||||
|
|
||||||
error: aborting due to previous error; 2 warnings emitted
|
error: aborting due to previous error; 2 warnings emitted
|
||||||
|
|
||||||
|
|
21
src/test/ui/consts/const-eval/erroneous-const2.rs
Normal file
21
src/test/ui/consts/const-eval/erroneous-const2.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//! Make sure we error on erroneous consts even if they are unused.
|
||||||
|
#![warn(const_err, unconditional_panic)]
|
||||||
|
|
||||||
|
struct PrintName<T>(T);
|
||||||
|
impl<T> PrintName<T> {
|
||||||
|
const VOID: () = [()][2]; //~WARN any use of this value will cause an error
|
||||||
|
//~^ WARN this operation will panic at runtime
|
||||||
|
//~| WARN this was previously accepted by the compiler but is being phased out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static FOO: () = {
|
||||||
|
if false {
|
||||||
|
// This bad constant is only used in dead code in a static initializer... and yet we still
|
||||||
|
// must make sure that the build fails.
|
||||||
|
let _ = PrintName::<i32>::VOID; //~ERROR could not evaluate static initializer
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
FOO
|
||||||
|
}
|
37
src/test/ui/consts/const-eval/erroneous-const2.stderr
Normal file
37
src/test/ui/consts/const-eval/erroneous-const2.stderr
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
warning: this operation will panic at runtime
|
||||||
|
--> $DIR/erroneous-const2.rs:6:22
|
||||||
|
|
|
||||||
|
LL | const VOID: () = [()][2];
|
||||||
|
| ^^^^^^^ index out of bounds: the length is 1 but the index is 2
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/erroneous-const2.rs:2:20
|
||||||
|
|
|
||||||
|
LL | #![warn(const_err, unconditional_panic)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
warning: any use of this value will cause an error
|
||||||
|
--> $DIR/erroneous-const2.rs:6:22
|
||||||
|
|
|
||||||
|
LL | const VOID: () = [()][2];
|
||||||
|
| -----------------^^^^^^^-
|
||||||
|
| |
|
||||||
|
| index out of bounds: the length is 1 but the index is 2
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/erroneous-const2.rs:2:9
|
||||||
|
|
|
||||||
|
LL | #![warn(const_err, unconditional_panic)]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= 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>
|
||||||
|
|
||||||
|
error[E0080]: could not evaluate static initializer
|
||||||
|
--> $DIR/erroneous-const2.rs:15:17
|
||||||
|
|
|
||||||
|
LL | let _ = PrintName::<i32>::VOID;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
||||||
|
error: aborting due to previous error; 2 warnings emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
|
@ -1,12 +1,12 @@
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:13:5
|
--> $DIR/promoted_errors.rs:15:5
|
||||||
|
|
|
|
||||||
LL | 0 - 1
|
LL | 0 - 1
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
| |
|
| |
|
||||||
| attempt to compute `0_u32 - 1_u32`, which would overflow
|
| attempt to compute `0_u32 - 1_u32`, which would overflow
|
||||||
| inside `overflow` at $DIR/promoted_errors.rs:13:5
|
| inside `overflow` at $DIR/promoted_errors.rs:15:5
|
||||||
| inside `X` at $DIR/promoted_errors.rs:33:29
|
| inside `X` at $DIR/promoted_errors.rs:38:29
|
||||||
...
|
...
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
@ -18,7 +18,7 @@ LL | | };
|
||||||
| |__-
|
| |__-
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/promoted_errors.rs:9:9
|
--> $DIR/promoted_errors.rs:11:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -26,7 +26,7 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:33:28
|
--> $DIR/promoted_errors.rs:38:28
|
||||||
|
|
|
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:18:5
|
--> $DIR/promoted_errors.rs:20:5
|
||||||
|
|
|
|
||||||
LL | 1 / 0
|
LL | 1 / 0
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
| |
|
| |
|
||||||
| attempt to divide `1_i32` by zero
|
| attempt to divide `1_i32` by zero
|
||||||
| inside `div_by_zero1` at $DIR/promoted_errors.rs:18:5
|
| inside `div_by_zero1` at $DIR/promoted_errors.rs:20:5
|
||||||
| inside `X` at $DIR/promoted_errors.rs:36:29
|
| inside `X` at $DIR/promoted_errors.rs:41:29
|
||||||
...
|
...
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
@ -18,7 +18,7 @@ LL | | };
|
||||||
| |__-
|
| |__-
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/promoted_errors.rs:9:9
|
--> $DIR/promoted_errors.rs:11:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -26,7 +26,7 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:36:28
|
--> $DIR/promoted_errors.rs:41:28
|
||||||
|
|
|
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:13:5
|
--> $DIR/promoted_errors.rs:15:5
|
||||||
|
|
|
|
||||||
LL | 0 - 1
|
LL | 0 - 1
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
| |
|
| |
|
||||||
| attempt to compute `0_u32 - 1_u32`, which would overflow
|
| attempt to compute `0_u32 - 1_u32`, which would overflow
|
||||||
| inside `overflow` at $DIR/promoted_errors.rs:13:5
|
| inside `overflow` at $DIR/promoted_errors.rs:15:5
|
||||||
| inside `X` at $DIR/promoted_errors.rs:33:29
|
| inside `X` at $DIR/promoted_errors.rs:38:29
|
||||||
...
|
...
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
@ -18,7 +18,7 @@ LL | | };
|
||||||
| |__-
|
| |__-
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/promoted_errors.rs:9:9
|
--> $DIR/promoted_errors.rs:11:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -26,7 +26,7 @@ LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/promoted_errors.rs:33:28
|
--> $DIR/promoted_errors.rs:38:28
|
||||||
|
|
|
|
||||||
LL | / const X: () = {
|
LL | / const X: () = {
|
||||||
LL | | let _x: &'static u32 = &overflow();
|
LL | | let _x: &'static u32 = &overflow();
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
// ignore-pass (test emits codegen-time warnings and verifies that they are not errors)
|
// ignore-pass (test emits codegen-time warnings and verifies that they are not errors)
|
||||||
|
|
||||||
|
//! This test ensures that when we promote code that fails to evaluate, the build still succeeds.
|
||||||
|
|
||||||
#![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
#![warn(const_err, arithmetic_overflow, unconditional_panic)]
|
||||||
|
|
||||||
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
|
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
|
||||||
|
@ -29,6 +31,9 @@ const fn oob() -> i32 {
|
||||||
[1, 2, 3][4]
|
[1, 2, 3][4]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An unused constant containing failing promoteds.
|
||||||
|
// This should work as long as `const_err` can be turned into just a warning;
|
||||||
|
// once it turns into a hard error, just remove `X`.
|
||||||
const X: () = {
|
const X: () = {
|
||||||
let _x: &'static u32 = &overflow();
|
let _x: &'static u32 = &overflow();
|
||||||
//[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
|
//[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
|
||||||
|
@ -41,4 +46,21 @@ const X: () = {
|
||||||
let _x: &'static i32 = &oob();
|
let _x: &'static i32 = &oob();
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {}
|
const fn mk_false() -> bool { false }
|
||||||
|
|
||||||
|
// An actually used constant referencing failing promoteds in dead code.
|
||||||
|
// This needs to always work.
|
||||||
|
const Y: () = {
|
||||||
|
if mk_false() {
|
||||||
|
let _x: &'static u32 = &overflow();
|
||||||
|
let _x: &'static i32 = &div_by_zero1();
|
||||||
|
let _x: &'static i32 = &div_by_zero2();
|
||||||
|
let _x: &'static i32 = &div_by_zero3();
|
||||||
|
let _x: &'static i32 = &oob();
|
||||||
|
}
|
||||||
|
()
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _y = Y;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue