Skip to content

Use the informative error as the main const eval error message #141698

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

Merged
merged 2 commits into from
Jun 4, 2025
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ const_eval_dyn_call_not_a_method =
`dyn` call trying to call something that is not a method
const_eval_error = {$error_kind ->
[static] could not evaluate static initializer
[const] evaluation of constant value failed
[const_with_path] evaluation of `{$instance}` failed
[static] evaluation of static initializer failed here
[const] evaluation of constant value failed here
[const_with_path] evaluation of `{$instance}` failed here
*[other] {""}
}
Expand Down
20 changes: 8 additions & 12 deletions compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::mem;

use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
Expand Down Expand Up @@ -131,10 +131,10 @@ pub fn get_span_and_frames<'tcx>(

/// Create a diagnostic for a const eval error.
///
/// This will use the `mk` function for creating the error which will get passed labels according to
/// the `InterpError` and the span and a stacktrace of current execution according to
/// `get_span_and_frames`.
pub(super) fn report<'tcx, C, F, E>(
/// This will use the `mk` function for adding more information to the error.
/// You can use it to add a stacktrace of current execution according to
/// `get_span_and_frames` or just give context on where the const eval error happened.
pub(super) fn report<'tcx, C, F>(
tcx: TyCtxt<'tcx>,
error: InterpErrorKind<'tcx>,
span: Span,
Expand All @@ -143,8 +143,7 @@ pub(super) fn report<'tcx, C, F, E>(
) -> ErrorHandled
where
C: FnOnce() -> (Span, Vec<FrameNote>),
F: FnOnce(Span, Vec<FrameNote>) -> E,
E: Diagnostic<'tcx>,
F: FnOnce(&mut Diag<'_>, Span, Vec<FrameNote>),
{
// Special handling for certain errors
match error {
Expand All @@ -163,20 +162,17 @@ where
_ => {
let (our_span, frames) = get_span_and_frames();
let span = span.substitute_dummy(our_span);
let err = mk(span, frames);
let mut err = tcx.dcx().create_err(err);
let mut err = tcx.dcx().struct_span_err(our_span, error.diagnostic_message());
// We allow invalid programs in infallible promoteds since invalid layouts can occur
// anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
let allowed_in_infallible = matches!(
error,
InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
);

let msg = error.diagnostic_message();
error.add_args(&mut err);

// Use *our* span to label the interp error
err.span_label(our_span, msg);
mk(&mut err, span, frames);
let g = err.emit();
let reported = if allowed_in_infallible {
ReportedErrorInfo::allowed_in_infallible(g)
Expand Down
34 changes: 27 additions & 7 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::sync::atomic::Ordering::Relaxed;

use either::{Left, Right};
use rustc_abi::{self as abi, BackendRepr};
use rustc_errors::E0080;
use rustc_hir::def::DefKind;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo};
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
Expand Down Expand Up @@ -290,12 +291,18 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|error| {
let span = tcx.def_span(def_id);

// FIXME(oli-obk): why don't we have any tests for this code path?
super::report(
tcx,
error.into_kind(),
span,
|| (span, vec![]),
|span, _| errors::NullaryIntrinsicError { span },
|diag, span, _| {
diag.span_label(
span,
crate::fluent_generated::const_eval_nullary_intrinsic_fail,
);
},
)
},
);
Expand Down Expand Up @@ -443,11 +450,15 @@ fn report_eval_error<'tcx>(
error,
DUMMY_SP,
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
|span, frames| errors::ConstEvalError {
span,
error_kind: kind,
instance,
frame_notes: frames,
|diag, span, frames| {
// FIXME(oli-obk): figure out how to use structured diagnostics again.
diag.code(E0080);
diag.span_label(span, crate::fluent_generated::const_eval_error);
diag.arg("instance", instance);
diag.arg("error_kind", kind);
for frame in frames {
diag.subdiagnostic(frame);
}
Copy link
Member

Choose a reason for hiding this comment

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

Please add a comment explaining what we are doing here and why. Why is the error code now repeated in a bunch of places where it was central before? Seems like this is now doing by hand what previously was done by the derive macros for the diagnostic types? Is there no way to still use a diagnostic type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is, but not without the aforementioned refactoring

Copy link
Member

Choose a reason for hiding this comment

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

Is it because diagnostic error types need to have a single fixed primary message and can't read it from their fields or have it otherwise altered?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

they can read it from their fields, but it needs work to set up as we can't just use the enums we have, or even just use a fluent identifier as a derive field. We'd have to eagerly format the error to a string, put that in a field and then make the derive just print that field. But that also needs a refactoring because the current logic isn't set up to do that

},
)
}
Expand Down Expand Up @@ -477,6 +488,15 @@ fn report_validation_error<'tcx>(
error,
DUMMY_SP,
|| crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes },
move |diag, span, frames| {
// FIXME(oli-obk): figure out how to use structured diagnostics again.
diag.code(E0080);
diag.span_label(span, crate::fluent_generated::const_eval_validation_failure);
diag.note(crate::fluent_generated::const_eval_validation_failure_note);
for frame in frames {
diag.subdiagnostic(frame);
}
diag.subdiagnostic(raw_bytes);
},
)
}
32 changes: 0 additions & 32 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,38 +439,6 @@ pub struct LiveDrop<'tcx> {
pub dropped_at: Span,
}

#[derive(Diagnostic)]
#[diag(const_eval_error, code = E0080)]
pub struct ConstEvalError {
#[primary_span]
pub span: Span,
/// One of "const", "const_with_path", and "static"
pub error_kind: &'static str,
pub instance: String,
#[subdiagnostic]
pub frame_notes: Vec<FrameNote>,
}

#[derive(Diagnostic)]
#[diag(const_eval_nullary_intrinsic_fail)]
pub struct NullaryIntrinsicError {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(const_eval_validation_failure, code = E0080)]
pub struct ValidationFailure {
#[primary_span]
pub span: Span,
#[note(const_eval_validation_failure_note)]
pub ub_note: (),
#[subdiagnostic]
pub frames: Vec<FrameNote>,
#[subdiagnostic]
pub raw_bytes: RawBytesNote,
}

pub trait ReportErrorExt {
/// Returns the diagnostic message for this error.
fn diagnostic_message(&self) -> DiagMessage;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/indexing_slicing_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn main() {
// This should be linted, since `suppress-restriction-lint-in-const` default is false.
const { &ARR[idx4()] };
//~^ ERROR: indexing may panic
//~| ERROR: evaluation of `main
//~| ERROR: index out of bounds

let y = &x;
// Ok, referencing shouldn't affect this lint. See the issue 6021
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/tests/ui/indexing_slicing_index.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
= note: `-D clippy::indexing-slicing` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`

error[E0080]: evaluation of `main::{constant#3}` failed
error[E0080]: index out of bounds: the length is 2 but the index is 4
--> tests/ui/indexing_slicing_index.rs:69:14
|
LL | const { &ARR[idx4()] };
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
| ^^^^^^^^^^^ evaluation of `main::{constant#3}` failed here

note: erroneous constant encountered
--> tests/ui/indexing_slicing_index.rs:69:5
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail/const-ub-checks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const UNALIGNED_READ: () = unsafe {
let x = &[0u8; 4];
let ptr = x.as_ptr().cast::<u32>();
ptr.read(); //~ERROR: evaluation of constant value failed
ptr.read(); //~ERROR: accessing memory based on pointer with alignment 1, but alignment 4 is required
};

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail/const-ub-checks.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required
--> tests/fail/const-ub-checks.rs:LL:CC
|
LL | ptr.read();
| ^^^^^^^^^^ accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required
| ^^^^^^^^^^ evaluation of constant value failed here

note: erroneous constant encountered
--> tests/fail/const-ub-checks.rs:LL:CC
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail/erroneous_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

struct PrintName<T>(T);
impl<T> PrintName<T> {
const VOID: ! = panic!(); //~ERROR: evaluation of `PrintName::<i32>::VOID` failed
const VOID: ! = panic!(); //~ERROR: explicit panic
}

fn no_codegen<T>() {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail/erroneous_const.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
error[E0080]: evaluation panicked: explicit panic
--> tests/fail/erroneous_const.rs:LL:CC
|
LL | const VOID: ! = panic!();
| ^^^^^^^^ evaluation panicked: explicit panic
| ^^^^^^^^ evaluation of `PrintName::<i32>::VOID` failed here

note: erroneous constant encountered
--> tests/fail/erroneous_const.rs:LL:CC
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/fail/erroneous_const2.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const X: u32 = 5;
const Y: u32 = 6;
const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
//~^ERROR: evaluation of constant value failed
//~^ERROR: overflow

#[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/5391
fn main() {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail/erroneous_const2.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: attempt to compute `5_u32 - 6_u32`, which would overflow
--> tests/fail/erroneous_const2.rs:LL:CC
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow
| ^^^^^ evaluation of constant value failed here

note: erroneous constant encountered
--> tests/fail/erroneous_const2.rs:LL:CC
Expand Down
4 changes: 2 additions & 2 deletions tests/rustdoc-ui/const-evalutation-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::cell::Cell;
use std::mem;

pub struct S {
s: Cell<usize>
s: Cell<usize>,
}

pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
//~^ ERROR evaluation of constant value failed
//~^ ERROR overflow
4 changes: 2 additions & 2 deletions tests/rustdoc-ui/const-evalutation-ice.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: attempt to compute `0_usize - 1_usize`, which would overflow
--> $DIR/const-evalutation-ice.rs:10:22
|
LL | pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of constant value failed here

error: aborting due to 1 previous error

Expand Down
3 changes: 1 addition & 2 deletions tests/ui/array-slice-vec/array_const_index-0.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const A: &'static [i32] = &[];
const B: i32 = (&A)[1];
//~^ NOTE index out of bounds: the length is 0 but the index is 1
//~| ERROR evaluation of constant value failed
//~^ ERROR index out of bounds: the length is 0 but the index is 1

fn main() {
let _ = B;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/array-slice-vec/array_const_index-0.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: index out of bounds: the length is 0 but the index is 1
--> $DIR/array_const_index-0.rs:2:16
|
LL | const B: i32 = (&A)[1];
| ^^^^^^^ index out of bounds: the length is 0 but the index is 1
| ^^^^^^^ evaluation of constant value failed here

error: aborting due to 1 previous error

Expand Down
3 changes: 1 addition & 2 deletions tests/ui/array-slice-vec/array_const_index-1.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const A: [i32; 0] = [];
const B: i32 = A[1];
//~^ NOTE index out of bounds: the length is 0 but the index is 1
//~| ERROR evaluation of constant value failed
//~^ ERROR index out of bounds: the length is 0 but the index is 1

fn main() {
let _ = B;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/array-slice-vec/array_const_index-1.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: index out of bounds: the length is 0 but the index is 1
--> $DIR/array_const_index-1.rs:2:16
|
LL | const B: i32 = A[1];
| ^^^^ index out of bounds: the length is 0 but the index is 1
| ^^^^ evaluation of constant value failed here

error: aborting due to 1 previous error

Expand Down
8 changes: 4 additions & 4 deletions tests/ui/asm/fail-const-eval-issue-121099.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
error[E0080]: evaluation of `{global_asm#0}::{constant#0}` failed
error[E0080]: attempt to shift left by `500_i32`, which would overflow
--> $DIR/fail-const-eval-issue-121099.rs:8:31
|
LL | global_asm!("/* {} */", const 1 << 500);
| ^^^^^^^^ attempt to shift left by `500_i32`, which would overflow
| ^^^^^^^^ evaluation of `{global_asm#0}::{constant#0}` failed here

error[E0080]: evaluation of `{global_asm#1}::{constant#0}` failed
error[E0080]: attempt to divide `1_i32` by zero
--> $DIR/fail-const-eval-issue-121099.rs:10:31
|
LL | global_asm!("/* {} */", const 1 / 0);
| ^^^^^ attempt to divide `1_i32` by zero
| ^^^^^ evaluation of `{global_asm#1}::{constant#0}` failed here

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/associated-consts/defaults-not-assumed-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trait Tr {
// This should not be a constant evaluation error (overflow). The value of
// `Self::A` must not be assumed to hold inside the trait.
const B: u8 = Self::A + 1;
//~^ ERROR evaluation of `<() as Tr>::B` failed
//~^ ERROR overflow
}

// An impl that doesn't override any constant will NOT cause a const eval error
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-consts/defaults-not-assumed-fail.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of `<() as Tr>::B` failed
error[E0080]: attempt to compute `u8::MAX + 1_u8`, which would overflow
--> $DIR/defaults-not-assumed-fail.rs:9:19
|
LL | const B: u8 = Self::A + 1;
| ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
| ^^^^^^^^^^^ evaluation of `<() as Tr>::B` failed here

note: erroneous constant encountered
--> $DIR/defaults-not-assumed-fail.rs:34:16
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/borrowck/issue-81899.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//@ dont-require-annotations: NOTE

const _CONST: &[u8] = &f(&[], |_| {}); //~ ERROR evaluation of constant value failed
const _CONST: &[u8] = &f(&[], |_| {}); //~ ERROR explicit panic
//~^ NOTE constant

const fn f<F>(_: &[u8], _: F) -> &[u8]
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/issue-81899.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: evaluation panicked: explicit panic
--> $DIR/issue-81899.rs:6:24
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| ^^^^^^^^^^^^^^ evaluation panicked: explicit panic
| ^^^^^^^^^^^^^^ evaluation of constant value failed here
|
note: inside `f::<{closure@$DIR/issue-81899.rs:6:31: 6:34}>`
--> $DIR/issue-81899.rs:13:5
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/borrowck/issue-88434-minimal-example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

//@ dont-require-annotations: NOTE

const _CONST: &() = &f(&|_| {}); //~ ERROR evaluation of constant value failed
const _CONST: &() = &f(&|_| {}); //~ ERROR explicit panic
//~^ NOTE constant

const fn f<F>(_: &F)
Expand All @@ -12,4 +12,4 @@ where
panic!() //~ NOTE inside `f
}

fn main() { }
fn main() {}
Loading
Loading