Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#![recursion_limit] behaves strangely #75602

Open
RaphiJS6-13 opened this issue Aug 16, 2020 · 5 comments
Open

#![recursion_limit] behaves strangely #75602

RaphiJS6-13 opened this issue Aug 16, 2020 · 5 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@RaphiJS6-13
Copy link

RaphiJS6-13 commented Aug 16, 2020

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() { }
@RaphiJS6-13 RaphiJS6-13 added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 16, 2020
@ecstatic-morse ecstatic-morse removed the I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ label Aug 17, 2020
@lunacookies
Copy link
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.

@RaphiJS6-13
Copy link
Author

RaphiJS6-13 commented Sep 7, 2020

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

@jyn514
Copy link
Member

jyn514 commented Sep 7, 2020

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.

@RaphiJS6-13
Copy link
Author

RaphiJS6-13 commented Sep 7, 2020

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.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Sep 28, 2021
Improve help for recursion limit errors

- Tweak help message and suggested limit (handle `0` case).
- Add test for rust-lang#75602 (it was already fixed, maybe can be resolved too).

Fixes rust-lang#76424
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Sep 29, 2021
Improve help for recursion limit errors

- Tweak help message and suggested limit (handle `0` case).
- Add test for rust-lang#75602 (it was already fixed, maybe can be resolved too).

Fixes rust-lang#76424
ehuss added a commit to ehuss/rust that referenced this issue Sep 30, 2021
Improve help for recursion limit errors

- Tweak help message and suggested limit (handle `0` case).
- Add test for rust-lang#75602 (it was already fixed, maybe can be resolved too).

Fixes rust-lang#76424
@workingjubilee workingjubilee added the A-diagnostics Area: Messages for errors, warnings, and lints label Oct 11, 2021
@workingjubilee
Copy link
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants