Skip to content

Unconditional recursion in a const fn produces a massive diagnostic #92796

Closed
@PatchMixolydic

Description

@PatchMixolydic

Given the following code (playground):

#![allow(unused)]

const fn f<T>(x: T) {
    f(x);
}

const X: () = f(1);

The current output is:

Massive diagnostic
warning: function cannot return without recursing
 --> src/lib.rs:3:1
  |
3 | const fn f<T>(x: T) {
  | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing
4 |     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
 --> src/lib.rs:4:5
  |
4 |     f(x);
  |     ^^^^
  |     |
  |     reached the configured maximum number of stack frames
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     inside `X` at src/lib.rs:7:15
...
7 | 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>

Ideally, the duplicate lines should be hidden:

warning: function cannot return without recursing
 --> src/lib.rs:3:1
  |
3 | const fn f<T>(x: T) {
  | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing
4 |     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
 --> src/lib.rs:4:5
  |
4 |     f(x);
  |     ^^^^
  |     |
  |     reached the configured maximum number of stack frames
  |     inside `f::<i32>` at src/lib.rs:4:5
  |     [... inside N additional calls to `f::<i32>` ...]
  |     inside `X` at src/lib.rs:7:15
...
7 | 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>

@rustbot modify labels: +A-const-fn +D-verbose

Metadata

Metadata

Labels

A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-diagnosticsArea: Messages for errors, warnings, and lintsD-verboseDiagnostics: Too much output caused by a single piece of incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions