about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-01-11 17:55:56 -0800
committerMichael Goulet <michael@errs.io>2022-01-11 18:13:53 -0800
commit73ad8df70d94d318fea0df3079504bd23e5b4901 (patch)
treebe092ba6e237133fdfe7a304b2d51f935cccd164
parentcfa4ac66c194046f631ce076c75516ecfdeb77ee (diff)
downloadrust-73ad8df70d94d318fea0df3079504bd23e5b4901.tar.gz
rust-73ad8df70d94d318fea0df3079504bd23e5b4901.zip
Deduplicate lines in long const-eval stack trace
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs30
-rw-r--r--src/test/ui/consts/recursive.rs11
-rw-r--r--src/test/ui/consts/recursive.stderr31
3 files changed, 71 insertions, 1 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 87298023980..89a0f8245e5 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 00000000000..664940c52cf
--- /dev/null
+++ b/src/test/ui/consts/recursive.rs
@@ -0,0 +1,11 @@
+#![allow(unused)]
+
+const fn f<T>(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 00000000000..31ac1fff4e8
--- /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<T>(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::<i32>` at $DIR/recursive.rs:4:5
+   |     [... 126 additional calls inside `f::<i32>` 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 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to previous error; 1 warning emitted
+