Skip to content

Commit c81e751

Browse files
committed
Skip redundant frames in const recursion errors
``` error[E0080]: evaluation of constant value failed --> $DIR/infinite-recursion-const-fn.rs:4:5 | LL | b() | ^^^ reached the configured maximum number of stack frames | note: inside `a` --> $DIR/infinite-recursion-const-fn.rs:4:5 | LL | b() | ^^^ note: inside `b` --> $DIR/infinite-recursion-const-fn.rs:7:5 | LL | a() | ^^^ note: [... 125 additional calls ...] inside `b` --> $DIR/infinite-recursion-const-fn.rs:7:5 | LL | a() | ^^^ note: inside `ARR::{constant#0}` --> $DIR/infinite-recursion-const-fn.rs:9:18 | LL | const ARR: [i32; a()] = [5; 6]; | ^^^ ```
1 parent 8231065 commit c81e751

File tree

7 files changed

+16
-1252
lines changed

7 files changed

+16
-1252
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ const_eval_fn_ptr_call =
117117
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
118118
const_eval_frame_note = {$times ->
119119
[0] {const_eval_frame_note_inner}
120-
*[other] [... {$times} additional calls {const_eval_frame_note_inner} ...]
120+
*[other] [... {$times} additional calls ...] {const_eval_frame_note_inner}
121121
}
122122
123123
const_eval_frame_note_inner = inside {$where_ ->

compiler/rustc_const_eval/src/const_eval/error.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::mem;
22

3+
use rustc_data_structures::fx::FxHashSet;
34
use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
45
use rustc_middle::mir::AssertKind;
56
use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo};
@@ -9,7 +10,7 @@ use rustc_middle::ty::{ConstInt, TyCtxt};
910
use rustc_span::{Span, Symbol};
1011

1112
use super::CompileTimeMachine;
12-
use crate::errors::{self, FrameNote, ReportErrorExt};
13+
use crate::errors::{FrameNote, ReportErrorExt};
1314
use crate::interpret::{
1415
CtfeProvenance, ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType,
1516
Pointer, err_inval, err_machine_stop,
@@ -93,7 +94,7 @@ impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
9394
pub fn get_span_and_frames<'tcx>(
9495
tcx: TyCtxtAt<'tcx>,
9596
stack: &[Frame<'tcx, impl Provenance, impl Sized>],
96-
) -> (Span, Vec<errors::FrameNote>) {
97+
) -> (Span, Vec<FrameNote>) {
9798
let mut stacktrace = Frame::generate_stacktrace_from_stack(stack);
9899
// Filter out `requires_caller_location` frames.
99100
stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*tcx));
@@ -104,8 +105,8 @@ pub fn get_span_and_frames<'tcx>(
104105
// Add notes to the backtrace. Don't print a single-line backtrace though.
105106
if stacktrace.len() > 1 {
106107
// Helper closure to print duplicated lines.
107-
let mut add_frame = |mut frame: errors::FrameNote| {
108-
frames.push(errors::FrameNote { times: 0, ..frame.clone() });
108+
let mut add_frame = |mut frame: FrameNote| {
109+
frames.push(FrameNote { times: 0, ..frame.clone() });
109110
// Don't print [... additional calls ...] if the number of lines is small
110111
if frame.times < 3 {
111112
let times = frame.times;
@@ -116,21 +117,19 @@ pub fn get_span_and_frames<'tcx>(
116117
}
117118
};
118119

119-
let mut last_frame: Option<errors::FrameNote> = None;
120+
let mut last_frame: Option<FrameNote> = None;
121+
let mut seen = FxHashSet::default();
120122
for frame_info in &stacktrace {
121123
let frame = frame_info.as_note(*tcx);
122124
match last_frame.as_mut() {
123-
Some(last_frame)
124-
if last_frame.span == frame.span
125-
&& last_frame.where_ == frame.where_
126-
&& last_frame.instance == frame.instance =>
127-
{
125+
Some(last_frame) if !seen.insert(frame.clone()) => {
128126
last_frame.times += 1;
129127
}
130128
Some(last_frame) => {
131129
add_frame(mem::replace(last_frame, frame));
132130
}
133131
None => {
132+
seen.insert(frame.clone());
134133
last_frame = Some(frame);
135134
}
136135
}
@@ -219,7 +218,7 @@ pub(super) fn lint<'tcx, L>(
219218
tcx: TyCtxtAt<'tcx>,
220219
machine: &CompileTimeMachine<'tcx>,
221220
lint: &'static rustc_session::lint::Lint,
222-
decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
221+
decorator: impl FnOnce(Vec<FrameNote>) -> L,
223222
) where
224223
L: for<'a> rustc_errors::LintDiagnostic<'a, ()>,
225224
{

compiler/rustc_const_eval/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ pub(crate) struct NonConstImplNote {
264264
pub span: Span,
265265
}
266266

267-
#[derive(Clone)]
267+
#[derive(Clone, PartialEq, Eq, Hash)]
268268
pub struct FrameNote {
269269
pub span: Span,
270270
pub times: i32,

tests/ui/consts/recursive.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ error[E0080]: reached the configured maximum number of stack frames
1515
LL | const X: () = f(1);
1616
| ^^^^ evaluation of `X` failed inside this call
1717
|
18-
note: [... 126 additional calls inside `f::<i32>` ...]
18+
note: [... 126 additional calls ...] inside `f::<i32>`
1919
--> $DIR/recursive.rs:4:5
2020
|
2121
LL | f(x);

0 commit comments

Comments
 (0)