Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: Sorry for not having a very good small reproduce of this issue. Basically we found our code will stuck when compiling after upgrading compiler to nightly-2022-10-16. I suspect this is related to a not-so-recent change of trait normalization - I modified in the Rust compiler on the latest master and find that some part of code is producing a large number of obligations. The highest one hits 4052 obligations. Digging it into a little bit, we found that the root cause is the + , which produces ~50 obligations. And after some static dispatching with generic parameters, it exploded to 4052. For example, when we define something like , we will find about 4x50 obligations at the call site. If the code is wrapped in yet another enum that specializes some generics to two concrete types, it doubles again. Anyway, one interesting observation that can workaround the bug is here: Once we erase the concrete future type and replace it with BoxFuture, the compiler no longer stuck and there won't be a large number of obligations. Interestingly, any of the below changes will cause obligations to increase again: moving the function call into the match will increase number of obligations the original code before bumping toolchain When the compiler stuck, it is resolving obligations like follows, which might take ~1sec at each call site that awaits a future including a MergeIterator. nightly-07-29 <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --
Probably also related to RPITIT, as we make a intensive use of zero-overhead async trait with GAT:
I don't think changed behavior at all, but cc just in case I missed something. This probably could use bisection for a sudden spike in compile time anyways to find out where this actually regressed.
I wonder if this was due to .
I’ll do a bisect tomorrow
... but probably will take more time. is merged before which fixes a compiler bug. I'll need to bypass before bisecting into that date.
It's probably possible to just revert and check if that makes the program no longer slow to compile.
Yeah no prob, I'll have a try.
I reverted over latest master and it worked perfectly Thanks!
By "worked perfectly", you mean the slowness is gone? In that case, this issue probably needs minimization and I can then look at why the fix in is incomplete.
Yes. It compiles within 2 minutes. Previously it seems never end, I wait at least 5 minutes before killing cargo. Sure, I'll try minimizing it. From the PR description it sounds like a generator issue? I'll try combining futuresasyncstream with some complex types, which should reflect how our code work.
still trying to figure it out -- I've written some programs to generate 5k+ obligations, but it doesn't time out as the original code does. Anyway, still trying to make a MCVE.
Thanks so much for looking into this. I might also investigate, but I'm quite busy :sweat:
In the original code, the compiler resolves 50 obligations very slowly at each call side, about 1sec per call site. So I guess it's more related to the obligations itself instead of the numbers.
No prob, just wait until I got a minimum reproducible code, and it would be more efficient for you to look into
WG-prioritization assigning priority (). label -I-prioritize +P-high
Should we revert before the beta cutoff and try again? The diff isn't very complex after all
Though might be fixed by , I'll probably still look into this and make a mcve based on the reverted commit.
It would be very useful if you created an MCVE that demonstrates the regression, for a future attempt to fix it. Thanks
This took me days. I originally thought the root cause lies in one module of our system, and it turned out that a combination of multiple modules are causing this issue. MCVE here: Basically, we are doing 3 things here: Firstly, construct a complex nested iterator type, this will generate 5000 obligations on all call sites of . Secondly, construct and streams. Then, generate calls of . On (some commit on main), compiler will stuck. On nightly-2022-07-29 and , this works perfectly, Interestingly, without function, e.g., change L144 to like None of them will stuck. Therefore, I guess there's problem with function's lifetime?
<delWhat's more interesting, change 's signature to:</delThis cannot be reproduced stably. Ignore this comment. will ICE on (some commit on main)
I found a more simplified MCVE when workaround this bug in the codebase, without futures-async-stream. Trying to construct it...
do you have a branch of the full risingwave project that I can test the regression on?
Unluckily I got some strange ICEs when building the tower dependency, and the compiler crashed before I could test . Here's the branch for testing -, which will stuck with the configured rust-toolchain (2022-10-16). I'm using stage1 compiler artifacts and using the following command to compile:
... and the latest master will also panic with the tower dependency, so I guess the master branch is already broken? (Or there's something wrong with my build env)
Okay, I probably did the compile in a wrong way. Testing again, sorry for that
Here's what I did: Unluckily, doesn't seem to fix the issue. The rustc process keeps spinning at 100% CPU and seems never to complete when compiling
The branch for testing -

Discussion:
// This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. <del> ty::Opaque(def_id, substs) => { </del> <ins> ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { </ins> // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.super_fold_with(self),

// This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. <del> ty::Opaque(def_id, substs) => { </del> <ins> ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { </ins> // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.try_super_fold_with(self),

<ins> // known-bug: #103507 // failure-status: 101 // normalize-stderr-test "note: .*nn" -> "" // normalize-stderr-test "thread 'rustc' panicked.*n" -> "" // rustc-env:RUST_BACKTRACE=0 #![feature(type_alias_impl_trait)] #![feature(const_trait_impl)] #![feature(const_refs_to_cell)] #![feature(inline_const)] use std::marker::Destruct; trait T { type Item; } type Alias<'a> = impl T<Item = &'a ()>; struct S; impl<'a> T for &'a S { type Item = &'a (); } const fn filter_positive<'a>() -> &'a Alias<'a> { &&S } const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { fun(filter_positive()); } const fn foo(_: &Alias<'_>) {} const BAR: () = { with_positive(foo); }; fn main() {} </ins>

<ins> error: internal compiler error: compiler/rustc_middle/src/ty/normalize_erasing_regions.rs:198:90: Failed to normalize <for<'a, 'b> fn(&'a Alias<'b>) {foo} as std::ops::FnOnce<(&&S,)>>::Output, maybe try to call `try_normalize_erasing_regions` instead query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `BAR` #1 [eval_to_const_value_raw] simplifying constant for the type system `BAR` end of query stack error: aborting due to previous error </ins>

<del> #![feature(type_alias_impl_trait)] trait T { type Item; } type Alias<'a> = impl T<Item = &'a ()>; struct S; impl<'a> T for &'a S { type Item = &'a (); } fn filter_positive<'a>() -> Alias<'a> { &S } fn with_positive(fun: impl Fn(Alias<'_>)) { fun(filter_positive()); } fn main() { with_positive(|_| ()); } </del>