Rust: Unhelpful "overflow evaluating the requirement" error for infinitely recursive generators

Created on 1 Dec 2017  路  7Comments  路  Source: rust-lang/rust

Obviously this shouldn't actually work, due to the state type being infinitely sized (at least not without become/TCO for generators), but it should generate an error similar to recursive types.

playground link

Program:

#![feature(generators, conservative_impl_trait, generator_trait)]

use std::ops::{Generator, GeneratorState};

fn foo() -> impl Generator<Yield = (), Return = ()> {
    || {
        let mut gen = foo();

        let mut r = gen.resume();
        while let GeneratorState::Yielded(v) = r {
            yield v;
            r = gen.resume();
        }
    }
}

fn main() {
    foo();
}

Output:

   Compiling playground v0.0.1 (file:///playground)

thread 'rustc' has overflowed its stack
fatal runtime error: stack overflow
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Expected (something like):

   Compiling playground v0.0.1 (file:///playground)
error[E0072]: recursive type `Foo` has infinite size
 --> src/main.rs:1:1
  |
1 | struct Foo(Foo);
  | ^^^^^^^^^^^----^
  | |          |
  | |          recursive without indirection
  | recursive type has infinite size
  |
  = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable

error: aborting due to previous error

error: Could not compile `playground`.

To learn more, run the command again with --verbose.
A-diagnostics A-generators C-enhancement T-compiler

All 7 comments

Got the same error, using the futures-await crate. Here is a demo project to reproduce the issue, using the mentioned crate.

Getting the same error, by adapting my project using futures-await.

After updated to the latest nightly rust. The error message have been changed.
This reminds me that it is not related to generator at all. The overflow was caused by recursive type inference.
For the futures-await case, just change your #[async] to #[async(boxed)] to make the return value a concrete type instead.
In the generator case, try this one

#![feature(generators, conservative_impl_trait, generator_trait)]

use std::ops::{Generator, GeneratorState};

fn foo() -> Box<Generator<Yield = (), Return = ()>> {
    Box::new(|| {
        let mut gen = foo();

        let mut r = gen.resume();
        while let GeneratorState::Yielded(v) = r {
            yield v;
            r = gen.resume();
        }
    })
}

It compiled with no error.

This now gives the following error, which is still not particularly great.

error[E0275]: overflow evaluating the requirement `impl std::ops::Generator`
  |
  = help: consider adding a `#![recursion_limit="128"]` attribute to your crate

error: aborting due to previous error

Recursive closures also give a similar error:

error[E0275]: overflow evaluating the requirement `impl std::ops::Fn<()>`
#![feature(conservative_impl_trait)]

fn foo() -> impl Fn() {
    let t = foo();
    move || {
        t();
    }
}

fn main() {
    (foo())();
}

So this is no longer an ICE. The I-ICE label could be dropped.

I'm currently running into this while porting mysql_async to std::future (and thereby async fn) in https://github.com/blackbeam/mysql_async/pull/71. The compiler is also here generating the relatively unhelpful error message:

    Checking mysql_async v0.21.0-alpha.1 (/home/jon/dev/others/mysql_async)
error[E0275]: overflow evaluating the requirement `impl core::future::future::Future`
  |
  = help: consider adding a `#![recursion_limit="2048"]` attribute to your crate

error: aborting due to previous error

Is there a way to get information about _which_ async fn is causing the issue?

For completeness, if I increase the recursion limit the way it suggests up to 8192, rustc eventually crashes with

hread 'rustc' has overflowed its stack
fatal runtime error: stack overflow
error: Could not compile `mysql_async`.
Was this page helpful?
0 / 5 - 0 ratings