Rollup merge of #81333 - RalfJung:const-err-simplify, r=oli-obk

clean up some const error reporting around promoteds

These are some error reporting simplifications enabled by https://github.com/rust-lang/rust/pull/80579.

Further simplifications are possible but could be blocked on making `const_err` a hard error.

r? ``````@oli-obk``````
This commit is contained in:
Yuki Okushi 2021-01-29 09:17:38 +09:00 committed by GitHub
commit 046a414c19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 66 additions and 144 deletions

View file

@ -134,11 +134,9 @@ pub(crate) fn codegen_constant<'tcx>(
{ {
Ok(const_val) => const_val, Ok(const_val) => const_val,
Err(_) => { Err(_) => {
if promoted.is_none() { fx.tcx
fx.tcx .sess
.sess .span_err(constant.span, "erroneous constant encountered");
.span_err(constant.span, "erroneous constant encountered");
}
return crate::trap::trap_unreachable_ret_value( return crate::trap::trap_unreachable_ret_value(
fx, fx,
fx.layout_of(const_.ty), fx.layout_of(const_.ty),

View file

@ -30,12 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.tcx() .tcx()
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
.map_err(|err| { .map_err(|err| {
if promoted.is_none() { self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
self.cx
.tcx()
.sess
.span_err(constant.span, "erroneous constant encountered");
}
err err
}), }),
ty::ConstKind::Value(value) => Ok(value), ty::ConstKind::Value(value) => Ok(value),

View file

@ -298,6 +298,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx.def_span(def.did), tcx.def_span(def.did),
key.param_env, key.param_env,
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
MemoryExtra { can_access_statics: is_static }, MemoryExtra { can_access_statics: is_static },
); );
@ -305,83 +307,35 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
Err(error) => { Err(error) => {
let err = ConstEvalErr::new(&ecx, error, None); let err = ConstEvalErr::new(&ecx, error, None);
// errors in statics are always emitted as fatal errors // Some CTFE errors raise just a lint, not a hard error; see
if is_static { // <https://github.com/rust-lang/rust/issues/71800>.
// Ensure that if the above error was either `TooGeneric` or `Reported` let emit_as_lint = if let Some(def) = def.as_local() {
// an error must be reported. // (Associated) consts only emit a lint, since they might be unused.
let v = err.report_as_error( matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
ecx.tcx.at(ecx.cur_span()),
"could not evaluate static initializer",
);
// If this is `Reveal:All`, then we need to make sure an error is reported but if
// this is `Reveal::UserFacing`, then it's expected that we could get a
// `TooGeneric` error. When we fall back to `Reveal::All`, then it will either
// succeed or we'll report this error then.
if key.param_env.reveal() == Reveal::All {
tcx.sess.delay_span_bug(
err.span,
&format!("static eval failure did not emit an error: {:#?}", v),
);
}
Err(v)
} else if let Some(def) = def.as_local() {
// constant defined in this crate, we can figure out a lint level!
match tcx.def_kind(def.did.to_def_id()) {
// constants never produce a hard error at the definition site. Anything else is
// a backwards compatibility hazard (and will break old versions of winapi for
// sure)
//
// note that validation may still cause a hard error on this very same constant,
// because any code that existed before validation could not have failed
// validation thus preventing such a hard error from being a backwards
// compatibility hazard
DefKind::Const | DefKind::AssocConst => {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
Err(err.report_as_lint(
tcx.at(tcx.def_span(def.did)),
"any use of this value will cause an error",
hir_id,
Some(err.span),
))
}
// promoting runtime code is only allowed to error if it references broken
// constants any other kind of error will be reported to the user as a
// deny-by-default lint
_ => {
if let Some(p) = cid.promoted {
let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span;
if let err_inval!(ReferencedConstant) = err.error {
Err(err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",
))
} else {
Err(err.report_as_lint(
tcx.at(span),
"reaching this expression at runtime will panic or abort",
tcx.hir().local_def_id_to_hir_id(def.did),
Some(err.span),
))
}
// anything else (array lengths, enum initializers, constant patterns) are
// reported as hard errors
} else {
Err(err.report_as_error(
ecx.tcx.at(ecx.cur_span()),
"evaluation of constant value failed",
))
}
}
}
} else { } else {
// use of broken constant from other crate // use of broken constant from other crate: always an error
Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")) false
};
if emit_as_lint {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
Err(err.report_as_lint(
tcx.at(tcx.def_span(def.did)),
"any use of this value will cause an error",
hir_id,
Some(err.span),
))
} else {
let msg = if is_static {
"could not evaluate static initializer"
} else {
"evaluation of constant value failed"
};
Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), msg))
} }
} }
Ok(mplace) => { Ok(mplace) => {
// Since evaluation had no errors, valiate the resulting constant: // Since evaluation had no errors, validate the resulting constant.
// This is a separate `try` block to provide more targeted error reporting.
let validation = try { let validation = try {
let mut ref_tracking = RefTracking::new(mplace); let mut ref_tracking = RefTracking::new(mplace);
let mut inner = false; let mut inner = false;
@ -399,7 +353,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
} }
}; };
if let Err(error) = validation { if let Err(error) = validation {
// Validation failed, report an error // Validation failed, report an error. This is always a hard error.
let err = ConstEvalErr::new(&ecx, error, None); let err = ConstEvalErr::new(&ecx, error, None);
Err(err.struct_error( Err(err.struct_error(
ecx.tcx, ecx.tcx,

View file

@ -31,7 +31,7 @@ impl Tr for u32 {
fn main() { fn main() {
assert_eq!(<() as Tr>::A, 255); assert_eq!(<() as Tr>::A, 255);
assert_eq!(<() as Tr>::B, 0); // causes the error above assert_eq!(<() as Tr>::B, 0); // causes the error above
//~^ ERROR evaluation of constant expression failed //~^ ERROR evaluation of constant value failed
//~| ERROR erroneous constant used //~| ERROR erroneous constant used
assert_eq!(<u8 as Tr>::A, 254); assert_eq!(<u8 as Tr>::A, 254);

View file

@ -8,15 +8,11 @@ LL | const B: u8 = Self::A + 1;
| |
= note: `#[deny(const_err)]` on by default = note: `#[deny(const_err)]` on by default
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/defaults-not-assumed-fail.rs:33:5 --> $DIR/defaults-not-assumed-fail.rs:33:16
| |
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
| ^^^^^^^^^^^-------------^^^^^ | ^^^^^^^^^^^^^ referenced constant has errors
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: erroneous constant used error: erroneous constant used
--> $DIR/defaults-not-assumed-fail.rs:33:5 --> $DIR/defaults-not-assumed-fail.rs:33:5

View file

@ -12,7 +12,7 @@ note: the lint level is defined here
LL | #![warn(const_err)] LL | #![warn(const_err)]
| ^^^^^^^^^ | ^^^^^^^^^
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/conditional_array_execution.rs:11:20 --> $DIR/conditional_array_execution.rs:11:20
| |
LL | println!("{}", FOO); LL | println!("{}", FOO);

View file

@ -21,6 +21,6 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error
fn main() { fn main() {
let x: &'static i32 = &X; let x: &'static i32 = &X;
//~^ ERROR evaluation of constant expression failed //~^ ERROR evaluation of constant value failed
println!("x={}", x); println!("x={}", x);
} }

View file

@ -12,13 +12,11 @@ note: the lint level is defined here
LL | #[warn(const_err)] LL | #[warn(const_err)]
| ^^^^^^^^^ | ^^^^^^^^^
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/const-eval-query-stack.rs:23:27 --> $DIR/const-eval-query-stack.rs:23:28
| |
LL | let x: &'static i32 = &X; LL | let x: &'static i32 = &X;
| ^- | ^ referenced constant has errors
| |
| referenced constant has errors
query stack during panic: query stack during panic:
#0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]` #0 [normalize_generic_arg_after_erasing_regions] normalizing `main::promoted[1]`
#1 [optimized_mir] optimizing MIR for `main` #1 [optimized_mir] optimizing MIR for `main`

View file

@ -18,7 +18,7 @@ const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
fn main() { fn main() {
assert_eq!(Y, 4); assert_eq!(Y, 4);
//~^ ERROR evaluation of constant expression failed //~^ ERROR evaluation of constant value failed
assert_eq!(Z, 4); assert_eq!(Z, 4);
//~^ ERROR evaluation of constant expression failed //~^ ERROR evaluation of constant value failed
} }

View file

@ -1,22 +1,14 @@
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/const_fn_ptr_fail2.rs:20:5 --> $DIR/const_fn_ptr_fail2.rs:20:16
| |
LL | assert_eq!(Y, 4); LL | assert_eq!(Y, 4);
| ^^^^^^^^^^^-^^^^^ | ^ referenced constant has errors
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/const_fn_ptr_fail2.rs:22:5 --> $DIR/const_fn_ptr_fail2.rs:22:16
| |
LL | assert_eq!(Z, 4); LL | assert_eq!(Z, 4);
| ^^^^^^^^^^^-^^^^^ | ^ referenced constant has errors
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: skipping const checks warning: skipping const checks
| |

View file

@ -12,8 +12,8 @@ fn main() {
const Y: u32 = foo(0 - 1); const Y: u32 = foo(0 - 1);
//~^ WARN any use of this value will cause //~^ WARN any use of this value will cause
println!("{} {}", X, Y); println!("{} {}", X, Y);
//~^ ERROR evaluation of constant expression failed //~^ ERROR evaluation of constant value failed
//~| ERROR evaluation of constant expression failed //~| ERROR evaluation of constant value failed
//~| WARN erroneous constant used [const_err] //~| WARN erroneous constant used [const_err]
//~| WARN erroneous constant used [const_err] //~| WARN erroneous constant used [const_err]
} }

View file

@ -20,7 +20,7 @@ LL | const Y: u32 = foo(0 - 1);
| | | |
| attempt to compute `0_u32 - 1_u32`, which would overflow | attempt to compute `0_u32 - 1_u32`, which would overflow
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/issue-43197.rs:14:23 --> $DIR/issue-43197.rs:14:23
| |
LL | println!("{} {}", X, Y); LL | println!("{} {}", X, Y);
@ -32,7 +32,7 @@ warning: erroneous constant used
LL | println!("{} {}", X, Y); LL | println!("{} {}", X, Y);
| ^ referenced constant has errors | ^ referenced constant has errors
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/issue-43197.rs:14:26 --> $DIR/issue-43197.rs:14:26
| |
LL | println!("{} {}", X, Y); LL | println!("{} {}", X, Y);

View file

@ -25,5 +25,5 @@ impl Foo for u16 {
fn main() { fn main() {
println!("{}", <Bar<u16, u8> as Foo>::AMT); println!("{}", <Bar<u16, u8> as Foo>::AMT);
//~^ ERROR evaluation of constant expression failed [E0080] //~^ ERROR evaluation of constant value failed [E0080]
} }

View file

@ -1,4 +1,4 @@
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/issue-44578.rs:27:20 --> $DIR/issue-44578.rs:27:20
| |
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT); LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);

View file

@ -8,13 +8,11 @@ LL | const BAR: usize = [5, 6, 7][T::BOO];
| |
= note: `#[deny(const_err)]` on by default = note: `#[deny(const_err)]` on by default
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/issue-50814-2.rs:18:5 --> $DIR/issue-50814-2.rs:18:6
| |
LL | &<A<T> as Foo<T>>::BAR LL | &<A<T> as Foo<T>>::BAR
| ^--------------------- | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
| |
| referenced constant has errors
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -8,13 +8,11 @@ LL | const MAX: u8 = A::MAX + B::MAX;
| |
= note: `#[deny(const_err)]` on by default = note: `#[deny(const_err)]` on by default
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/issue-50814.rs:20:5 --> $DIR/issue-50814.rs:20:6
| |
LL | &Sum::<U8,U8>::MAX LL | &Sum::<U8,U8>::MAX
| ^----------------- | ^^^^^^^^^^^^^^^^^ referenced constant has errors
| |
| referenced constant has errors
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -20,15 +20,11 @@ note: the lint level is defined here
LL | #[warn(const_err)] LL | #[warn(const_err)]
| ^^^^^^^^^ | ^^^^^^^^^
error[E0080]: evaluation of constant expression failed error[E0080]: evaluation of constant value failed
--> $DIR/const_unsafe_unreachable_ub.rs:17:3 --> $DIR/const_unsafe_unreachable_ub.rs:17:14
| |
LL | assert_eq!(BAR, true); LL | assert_eq!(BAR, true);
| ^^^^^^^^^^^---^^^^^^^^ | ^^^ referenced constant has errors
| |
| referenced constant has errors
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: erroneous constant used error: erroneous constant used
--> $DIR/const_unsafe_unreachable_ub.rs:17:3 --> $DIR/const_unsafe_unreachable_ub.rs:17:3

View file

@ -2,15 +2,12 @@ error[E0080]: values of the type `[u8; SIZE]` are too big for the current archit
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
| |
LL | intrinsics::size_of::<T>() LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
| |
| inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
| inside `main` at $DIR/issue-55878.rs:7:26
| |
::: $DIR/issue-55878.rs:7:26 ::: $DIR/issue-55878.rs:7:26
| |
LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
| ---------------------------------------------- | ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26
error: erroneous constant used error: erroneous constant used
--> $DIR/issue-55878.rs:7:26 --> $DIR/issue-55878.rs:7:26