-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Compiler hangs on some types threading lifetimes through a carrier trait #102966
Comments
@rustbot label +C-bug +I-hang +T-compiler |
Using godbolt the first rustc version that starts hanging is 1.31. Not sure if this info is of any use. |
I demangled a trace a bit, and, if you imagine the left margin steadily increasing here as they're all nested, it looks like this but goes on a lot longer: Demangled trace
So we are maybe looking at a huge TyS object constructed recursively. It may be at least 1,110 levels deep, the bottom level happens to be a |
OK. Basically yep, it's a huge type object. When inferring outlives-predicates, we are stacking many many associated types on top of each other, producing types like Here's how this is formed, made from some extra debug-logging in the
As you can see, it alternates between rounds where Incidentally, we can make an even smaller repro by deleting trait Trait<'a> { type Assoc: 'a; }
struct Node<'node, T: Trait<'node>>(Var<'node, T::Assoc>, Option<T::Assoc>);
struct RGen<R>(std::marker::PhantomData<R>);
impl<'a, R: 'a> Trait<'a> for RGen<R> { type Assoc = R; }
struct Var<'var, R: 'var>(Box<Node<'var, RGen<R>>>); But essentially what happened here is we tricked the bound inference into recursively substituting a type into itself. It was only possible because we used an associated type, and rustc didn't simplify these (fully specified) associated type projections but rather just used the raw type constructions to check membership in the hashmap of previously added bounds. There are two issues here:
So: can we "evaluate" the associated type projection? In this case I feel like we can, because RGen exists, there's an implementation It seems to me a similar feat of inference was done for trait Trait { type Assoc; }
struct Infinite<T>(<T as Trait>::Assoc);
impl<T> Trait for T { type Assoc = Infinite<T>; } // overflow evaluating the requirement `Infinite<T>: Sized` |
One more thing, the explicit lifetime bounds on associated type bounds don't seem to be returned by the
Not sure if this is wrong. Due to rust/compiler/rustc_hir_analysis/src/collect/predicates_of.rs Lines 378 to 385 in 4bd3078
|
This avoids a compiler hang, see rust-lang#102966.
The following code hangs rustc stable 1.64, beta and nightly. It sits on 100% CPU doing rustc_middle things inside a
rustc_typeck::outlives::implicit_infer::infer_predicates > insert_outlives_predicate
operation. (Edit: by "rustc_middle things" I mean<rustc_middle::ty::TyS as core::cmp::Ord>::cmp
.) I've let it run for at least half an hour to no avail.You can change the code in a couple of small ways such that it won't hang.
T: 'a
and useT
instead ofG::R
. You would think that adding a carrier trait with the same bounds would not really change anything. But it does. (In my code, NodeGenerics has a bunch of different types attached to it, which are used in many different arms ofKind
. It makes everything a lot neater.)RGen<T>
to justRGen
and its implementation ofNodeGenerics
to have a constanttype R = ()
.'static
bounds in everywhere instead, i.e. make NodeGenerics taketype R: 'static
.I don't know why it's hanging on this, but rustc should never hang, so there you go. Bug report filed.
The text was updated successfully, but these errors were encountered: