rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.29k stars 12.72k forks source link

Compiler freeze #101406

Open zesterer opened 2 years ago

zesterer commented 2 years ago

I'd like to give a more descriptive name to this issue, but unfortunately I don't know enough about the internals of rustc to be more useful. To my uneducated eye, it seems like the Rust is choking on the obligation produced by the where bound on the Bar implementation.

I can't fully confirm that this is caused by GATs, but removing the generic lifetime on Bar::Ctx results in the compiler generating the more reasonable overflow evaluating the requirement error.

I tried this code:

#![feature(generic_associated_types)]

trait Bar {
    type Ctx<'a>;

    fn run<'a>(
        &mut self,
        ctx: &Self::Ctx<'a>,
    );
}

struct Foo<F>(F);

impl<F> Bar for Foo<F>
    where F: FnMut(&Self::Ctx<'_>)
{
    type Ctx<'a> = ();

    fn run<'a>(
        &mut self,
        ctx: &Self::Ctx<'a>,
    ) {
        (self.0)(ctx)
    }
}

I expected to see this happen: The compiler to not freeze

Instead, this happened: The compiler froze

Meta

rustc --version --verbose:

rustc 1.65.0-nightly (c07a8b4e0 2022-08-26)
binary: rustc
commit-hash: c07a8b4e09f356c7468b69c50cac7fc5b5000b8a
commit-date: 2022-08-26
host: x86_64-unknown-linux-gnu
release: 1.65.0-nightly
LLVM version: 15.0.0
compiler-errors commented 2 years ago

Setting the recursion limit to be very small (like #![recursion_limit = "15"]) makes this complete within a reasonable time frame. This can also be kinda replicated without GATs like so:

trait Bar<'a> {
    type Ctx;

    fn run(
        &mut self,
        ctx: &Self::Ctx,
    );
}

struct Foo<F>(F);

impl<'a, F> Bar<'a> for Foo<F>
    where F: FnMut(&<Self as Bar<'_>>::Ctx)
{
    type Ctx = ();

    fn run(
        &mut self,
        ctx: &Self::Ctx,
    ) {
        (self.0)(ctx)
    }
}

(The code isn't exactly the same -- but that's another way of getting it to hang in the same way)

jackh726 commented 2 years ago

Yes, this is not a GATs bug, but more of an associated types bug. There are some related issues (that I don't have links to right now). IIRC, the problem stems from using the associated type in the impl where clauses - we try to normalize that and get in a loop.