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

Recursive function call generates confusing overflow message #72577

Closed
o0Ignition0o opened this issue May 25, 2020 · 3 comments
Closed

Recursive function call generates confusing overflow message #72577

o0Ignition0o opened this issue May 25, 2020 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-traits Area: Trait system C-enhancement Category: An issue proposing an enhancement or a PR with one. D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@o0Ignition0o
Copy link
Contributor

o0Ignition0o commented May 25, 2020

error[E0275]: overflow evaluating the requirement &mut bytes::bytes_mut::BytesMut: bytes::buf::buf_impl::Buf

Here's a link to the playground : https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e0d226183c371b79d9a234ccebdeafd0

I tried this code:

use bytes::{Buf, BytesMut};

fn get_value<B>(buf: &mut B) -> Result<i32, String>
where
    B: Buf,
{
    Ok(42)
}

fn do_more<B>(mut buf: B) -> Result<i32, String>
where
    B: Buf,
{
    if buf.has_remaining() {
        get_value(&mut buf)
    } else {
        do_more(&mut buf)
    }
}

fn main() {
    let payload = vec![1, 2, 3, 4, 5];
    let parsed = do_more(&mut BytesMut::from(&*payload)).unwrap();
}

I expected to see this happen: Nothing really, but I would love to see an error message that would help me out here ^^.

Instead, this happened:

image

Meta

rustc --version --verbose:

playground (stable) and tested it on my machine: rustc 1.43.1 (8d69840ab 2020-05-04)

Link to the twitter discussion https://twitter.com/ekuber/status/1264962969206525952?s=20

Paging @estebank who might be interested <3

@o0Ignition0o o0Ignition0o added the C-bug Category: This is a bug. label May 25, 2020
@o0Ignition0o o0Ignition0o changed the title error[E0275]: overflow evaluating the requirement &mut bytes::bytes_mut::BytesMut: bytes::buf::buf_impl::Buf Error message that's a bit hard to figure out May 25, 2020
@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints A-traits Area: Trait system C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed C-bug Category: This is a bug. labels May 25, 2020
@Aaron1011
Copy link
Member

@o0Ignition0o: You can make this compile by changing get_value(&mut buf) to get_value(buf) - note that this will cause infinite recursion at runtime if buf.has_remaining() == false

Minimized:

struct BytesMut;

trait Buf {}

impl Buf for BytesMut {}
impl<'a, T: Buf> Buf for &'a mut T {}

fn do_more<B>(mut buf: B)
where
    B: Buf,
{
    do_more(&mut buf);
}

fn main() {
    do_more(&mut BytesMut)
}

Trying to monomorphize do_more::<B> causes us to recursively monomorphize do_more::<&mut B>, which will eventually hit the recursion limit.

We should be able to detect this kind of recursive monomorphization in simple cases (when the function directly calls itself rather than going through a helper function).

@o0Ignition0o
Copy link
Contributor Author

o0Ignition0o commented May 25, 2020

Oh thanks a lot! So long story short I should try to avoid recursion in this kind of scenario ? (the real life use case is a bit more complicated, but i was willing about to use recursion to solve it ^^')

thanks again :D

@estebank estebank added the D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. label May 27, 2020
@Aaron1011 Aaron1011 changed the title Error message that's a bit hard to figure out Recursive function call generates confusing overflow message May 28, 2020
Aaron1011 added a commit to Aaron1011/rust that referenced this issue Jun 22, 2020
This improves the output for issue rust-lang#72577, but there's still more work
to be done.

Currently, an overflow error during monomorphization results in an error
that points at the function we were unable to monomorphize. However, we
don't point at the call that caused the monomorphization to happen. In
the overflow occurs in a large recursive function, it may be difficult
to determine where the issue is.

This commit tracks and `Span` information during collection of
`MonoItem`s, which is used when emitting an overflow error. `MonoItem`
itself is unchanged, so this only affects
`src/librustc_mir/monomorphize/collector.rs`
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 23, 2020
…err, r=ecstatic-morse

Point at the call span when overflow occurs during monomorphization

This improves the output for issue rust-lang#72577, but there's still more work
to be done.

Currently, an overflow error during monomorphization results in an error
that points at the function we were unable to monomorphize. However, we
don't point at the call that caused the monomorphization to happen. In
the overflow occurs in a large recursive function, it may be difficult
to determine where the issue is.

This commit tracks and `Span` information during collection of
`MonoItem`s, which is used when emitting an overflow error. `MonoItem`
itself is unchanged, so this only affects
`src/librustc_mir/monomorphize/collector.rs`
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 23, 2020
…err, r=ecstatic-morse

Point at the call span when overflow occurs during monomorphization

This improves the output for issue rust-lang#72577, but there's still more work
to be done.

Currently, an overflow error during monomorphization results in an error
that points at the function we were unable to monomorphize. However, we
don't point at the call that caused the monomorphization to happen. In
the overflow occurs in a large recursive function, it may be difficult
to determine where the issue is.

This commit tracks and `Span` information during collection of
`MonoItem`s, which is used when emitting an overflow error. `MonoItem`
itself is unchanged, so this only affects
`src/librustc_mir/monomorphize/collector.rs`
@estebank
Copy link
Contributor

Current output:

error: reached the recursion limit while instantiating `do_more::<&mut &mut &mut &mut &mut ...>`
  --> src/main.rs:17:9
   |
17 |         do_more(&mut buf)
   |         ^^^^^^^^^^^^^^^^^
   |
note: `do_more` defined here
  --> src/main.rs:10:1
   |
10 | / fn do_more<B>(mut buf: B) -> Result<i32, String>
11 | | where
12 | |     B: Buf,
   | |___________^
   = note: the full type name has been written to '/playground/target/debug/deps/playground-b0d2208020a7eb98.long-type.txt'

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 A-traits Area: Trait system C-enhancement Category: An issue proposing an enhancement or a PR with one. D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. 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

4 participants