diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 87298023980ed..89a0f8245e5fb 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -156,9 +156,37 @@ impl<'tcx> ConstEvalErr<'tcx> { } // Add spans for the stacktrace. Don't print a single-line backtrace though. if self.stacktrace.len() > 1 { + // Helper closure to print duplicated lines. + let mut flush_last_line = |last_frame, times| { + if let Some((line, span)) = last_frame { + err.span_label(span, &line); + // Don't print [... additional calls ...] if the number of lines is small + if times < 3 { + for _ in 0..times { + err.span_label(span, &line); + } + } else { + err.span_label( + span, + format!("[... {} additional calls {} ...]", times, &line), + ); + } + } + }; + + let mut last_frame = None; + let mut times = 0; for frame_info in &self.stacktrace { - err.span_label(frame_info.span, frame_info.to_string()); + let frame = (frame_info.to_string(), frame_info.span); + if last_frame.as_ref() == Some(&frame) { + times += 1; + } else { + flush_last_line(last_frame, times); + last_frame = Some(frame); + times = 0; + } } + flush_last_line(last_frame, times); } // Let the caller finish the job. emit(err) diff --git a/src/test/ui/consts/recursive.rs b/src/test/ui/consts/recursive.rs new file mode 100644 index 0000000000000..664940c52cfc5 --- /dev/null +++ b/src/test/ui/consts/recursive.rs @@ -0,0 +1,11 @@ +#![allow(unused)] + +const fn f(x: T) { //~ WARN function cannot return without recursing + f(x); + //~^ ERROR any use of this value will cause an error + //~| WARN this was previously accepted by the compiler +} + +const X: () = f(1); + +fn main() {} diff --git a/src/test/ui/consts/recursive.stderr b/src/test/ui/consts/recursive.stderr new file mode 100644 index 0000000000000..31ac1fff4e84e --- /dev/null +++ b/src/test/ui/consts/recursive.stderr @@ -0,0 +1,31 @@ +warning: function cannot return without recursing + --> $DIR/recursive.rs:3:1 + | +LL | const fn f(x: T) { + | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | f(x); + | ---- recursive call site + | + = note: `#[warn(unconditional_recursion)]` on by default + = help: a `loop` may express intention better if this is on purpose + +error: any use of this value will cause an error + --> $DIR/recursive.rs:4:5 + | +LL | f(x); + | ^^^^ + | | + | reached the configured maximum number of stack frames + | inside `f::` at $DIR/recursive.rs:4:5 + | [... 126 additional calls inside `f::` at $DIR/recursive.rs:4:5 ...] + | inside `X` at $DIR/recursive.rs:9:15 +... +LL | const X: () = f(1); + | ------------------- + | + = note: `#[deny(const_err)]` on by default + = 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 + +error: aborting due to previous error; 1 warning emitted +