Skip to content

#![recursion_limit] behaves strangely #75602

Description

@RaphiJS6-13

I was playing around with recursion_limit, and I realized that recursion_limit doesn't check for bad values. #![recursion_limit = "malformed"] fn main() {}, for example, compiles without error. Moreover, when set to 1, the Rust compiler raises a weird error:

error[E0275]: overflow evaluating the requirement `&Self: std::ops::DispatchFromDyn<&RustaceansAreAwesome>`
  |
  = help: consider adding a `#![recursion_limit="2"]` attribute to your crate

error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.

What is RustaceansAreAwesome? This code doesn't make any macro calls, yet somehow exceeds the recursion limit.

Version

rustc --version --verbose:

rustc 1.41.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.41.0
LLVM version: 9.0

Code

#![recursion_limit = "1"]
fn main() { }

Activity

  1. added
    C-bugCategory: This is a bug.
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Aug 16, 2020
  2. removed
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    on Aug 17, 2020
  3. lunacookies commented on Aug 30, 2020

    @lunacookies
    Contributor

    I’ve never worked on the Rust compiler before, so I doubt I’ll be of any help here, but I quickly ran a GitHub search for RustaceansAreAwesome on this repo and found this. No idea what it means but hopefully is helpful in some way.

  4. RaphiJS6-13 commented on Sep 7, 2020

    @RaphiJS6-13
    Author

    I found a similar, but more egregious bug. (See #76424). Should I merge them?

  5. jyn514 commented on Sep 7, 2020

    @jyn514
    Member

    This code doesn't make any macro calls, yet somehow exceeds the recursion limit.

    I'm pretty sure the recursion limit applies to all parts of the compiler, not just macros. So the bit about weird errors when the limit is 1 seems fine to me. But it should probably enforce that the limit is at least a number.

  6. RaphiJS6-13 commented on Sep 7, 2020

    @RaphiJS6-13
    Author

    This code doesn't make any macro calls, yet somehow exceeds the recursion limit.

    I'm pretty sure the recursion limit applies to all parts of the compiler, not just macros. So the bit about weird errors when the limit is 1 seems fine to me.

    Certainly, running rustc --explain E0275 confirms that:

    An evaluation of a trait requirement overflowed.
    Erroneous code example:
    
    trait Foo {}
    struct Bar<T>(T);
    impl<T> Foo for T where Bar<T>: Foo {}
    
    This error occurs when there was a recursive trait requirement that overflowed
    before it could be evaluated. This often means that there is an unbounded
    recursion in resolving some type bounds.
    To determine if a `T` is `Foo`, we need to check if `Bar<T>` is `Foo`. However,
    to do this check, we need to determine that `Bar<Bar<T>>` is `Foo`. To
    determine this, we check if `Bar<Bar<Bar<T>>>` is `Foo`, and so on. This is
    clearly a recursive requirement that can't be resolved directly.
    
    Consider changing your trait bounds so that they're less self-referential.
    

    But it should probably enforce that the limit is at least a number.

    Yes, of course the compiler should set a minimum recursion limit to avoid breaking things.

  7. added 2 commits that reference this issue on Sep 28, 2021
  8. added a commit that references this issue on Sep 30, 2021
  9. workingjubilee commented on Oct 11, 2021

    @workingjubilee
    Member

    Current version:

    #![recursion_limit = "1"]
    fn main() { }

    emits

       Compiling playground v0.0.1 (/playground)
    error: reached the recursion limit while instantiating `<fn() as FnOnce<()>>::call_once - shim(fn())`
        |
    note: `call_once` defined here
    
    error: could not compile `playground` due to previous error
    

    Note: for some reason this does not break if it is layered all on one line, like

    #![recursion_limit = "1"] fn main() { }

    So yeah, there's an unfortunate thing here where there are a bunch of implicit pieces of code embedded as part of fn main() that, if you lower the overflow requirement too far, it starts breaking their minimum recursion requirements, which results in confusing diagnostics. I am not sure how we would stop this, though, since it does not seem easy to automatically detect when the code is coming in from the lang startup.

    A mildly hackish answer might be that we could set a hard floor of a recursion requirement of 3, which stops this from breaking on such a trivial example.

  10. RodBurman commented on Aug 26, 2026

    @RodBurman

    This is the current state of play, using cargo 1.98.0 (797e8a9bc 2026-08-05):

    #![recursion_limit = "malformed"] fn main() { }
    

    Which compiles gives the error:

       Compiling reclim v0.1.0 (/Users/rod/code/rust/triage/2026/08/reclim)
    error: `limit` must be a non-negative integer
     --> src/main.rs:1:1
      |
    1 | #![recursion_limit = "malformed"] fn main() { }
      | ^^^^^^^^^^^^^^^^^^^^^-----------^
      |                      |
      |                      not a valid integer
    
    error: could not compile `reclim` (bin "reclim") due to 1 previous error
    

    Therefore the limit is checked to be well formed. Changing "malformed" to "1", changes the error to:

       Compiling reclim v0.1.0 (/Users/rod/code/rust/triage/2026/08/reclim)
    error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome>`
      |
      = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`reclim`)
    
    For more information about this error, try `rustc --explain E0275`.
    error: could not compile `reclim` (bin "reclim") due to 1 previous error
    

    Therefore the original issue is replicated on a single line of code. Changing the "1" to "2", also changes the error to:

       Compiling reclim v0.1.0 (/Users/rod/code/rust/triage/2026/08/reclim)
    error: queries overflow the depth limit!
        --> /Users/rod/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/process.rs:2691:9
         |
    2691 |         ExitCode::SUCCESS
         |         ^^^^^^^^^^^^^^^^^
         |
         = help: consider increasing the recursion limit by adding a `#![recursion_limit = "4"]` attribute to your crate (`reclim`)
         = note: query depth increased by 4 when simplifying constant for the type system `std::process::ExitCode::SUCCESS`
    
    error: could not compile `reclim` (bin "reclim") due to 1 previous error
    

    Change the "2" to "4" again changes the error to:

       Compiling reclim v0.1.0 (/Users/rod/code/rust/triage/2026/08/reclim)
    error: queries overflow the depth limit!
       --> /Users/rod/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:206:9
        |
    206 |         &move || crate::sys::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
        |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`reclim`)
        = note: query depth increased by 6 when computing layout of `&dyn core::ops::function::Fn() -> i32 + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe`
    
    error: could not compile `reclim` (bin "reclim") due to 1 previous error
    

    Change "4" to "8" and it builds, note 5 or more works. May be we should add a check for values <5 and a message that is the minimum valid recursion limit? Or are there code sequences with a lower recursion requirements? It seems unlikely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.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