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

large number of obligation produced in async code causing compiler stuck #103423

Closed
Tracked by #5977 ...
skyzh opened this issue Oct 23, 2022 · 28 comments · Fixed by #103509
Closed
Tracked by #5977 ...

large number of obligation produced in async code causing compiler stuck #103423

skyzh opened this issue Oct 23, 2022 · 28 comments · Fixed by #103509
Labels
C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-compiletime Issue: Problems and improvements with respect to compile times. P-high High priority regression-untriaged Untriaged performance or correctness regression.

Comments

@skyzh
Copy link
Contributor

skyzh commented Oct 23, 2022

Code

I tried this code:

risingwavelabs/risingwave#5119

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 -> #102651.

I modified normalize.rs 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 OrderedMergeIteratorInner + UnorderedMergeIteratorInner, which produces ~50 obligations. And after some static dispatching with generic parameters, it exploded to 4052. For example, when we define something like IteratorUnion<IteratorType1, IteratorType2, IteratorType3, IteratorType4>, 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:

https://github.com/risingwavelabs/risingwave/blob/a0b2a119d6b5843bde33f9937b0f1bed3e80e0c8/src/storage/src/hummock/iterator/merge_inner.rs#L306-L308
https://github.com/risingwavelabs/risingwave/blob/a0b2a119d6b5843bde33f9937b0f1bed3e80e0c8/src/storage/src/hummock/iterator/merge_inner.rs#L265-L267

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.

fn unsafe_boxed_static_future<F, O>(f: F) -> BoxFuture<'static, O>
where
    F: Future<Output = O> + Send,
{
    let b = f.boxed();
    unsafe { std::mem::transmute::<BoxFuture<'_, O>, BoxFuture<'static, O>>(b) }
}


        let f = unsafe_boxed_static_future(node.iter.next());

        match f.await {

Interestingly, any of the below changes will cause obligations to increase again:

moving the function call into the match will increase number of obligations

        match unsafe_boxed_static_future(node.iter.next()).await {

the original code before bumping toolchain

        match node.iter.next().await {

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.

normalize::<rustc_middle::ty::subst::GenericArg>: with 52 obligations
result=Ok([static generator@src/storage/src/hummock/iterator/mod.rs:381:55: 386:6])
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>, RePlaceholder(Placeholder { universe: U2, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::sstable::forward_sstable_iterator::SstableIterator>, RePlaceholder(Placeholder { universe: U3, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U4, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, usize>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, usize>, RePlaceholder(Placeholder { universe: U4, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>>, RePlaceholder(Placeholder { universe: U5, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, RePlaceholder(Placeholder { universe: U6, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U7, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U7, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U7, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U7, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, ()>, RePlaceholder(Placeholder { universe: U6, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Forward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, hummock::sstable::forward_sstable_iterator::SstableIterator>, RePlaceholder(Placeholder { universe: U8, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U9, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U9, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U9, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U9, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U6, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Forward>, RePlaceholder(Placeholder { universe: U6, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::forward_sstable_iterator::SstableIterator>, RePlaceholder(Placeholder { universe: U4, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U10, name: BrAnon(1) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U11, name: BrAnon(11) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U11, name: BrAnon(12) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::forward_sstable_iterator::SstableIterator, RePlaceholder(Placeholder { universe: U4, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>, RePlaceholder(Placeholder { universe: U12, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, usize>, hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, RePlaceholder(Placeholder { universe: U13, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U14, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, usize>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, usize>, RePlaceholder(Placeholder { universe: U14, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>>, RePlaceholder(Placeholder { universe: U15, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, RePlaceholder(Placeholder { universe: U16, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U17, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U17, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U17, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U17, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>, ReStatic), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::merge_inner::MergeIteratorInner<hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, ()>, RePlaceholder(Placeholder { universe: U16, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::HummockIteratorUnion<hummock::iterator::Backward, hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, RePlaceholder(Placeholder { universe: U18, name: BrAnon(3) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::shared_buffer::shared_buffer_batch::SharedBufferBatchIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U19, name: BrAnon(2) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U19, name: BrAnon(4) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U19, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U19, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U16, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::PhantomHummockIterator<hummock::iterator::Backward>, RePlaceholder(Placeholder { universe: U16, name: BrAnon(8) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::iterator::concat_inner::ConcatIteratorInner<hummock::sstable::backward_sstable_iterator::BackwardSstableIterator>, RePlaceholder(Placeholder { universe: U14, name: BrAnon(6) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U20, name: BrAnon(1) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U21, name: BrAnon(11) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U21, name: BrAnon(12) })), []), depth=0)
- Obligation(predicate=Binder(OutlivesPredicate(hummock::sstable::backward_sstable_iterator::BackwardSstableIterator, RePlaceholder(Placeholder { universe: U14, name: BrAnon(8) })), []), depth=0)

Version it worked on

nightly-07-29

Version with regression

5a0f454c021d9617c6c37ed2f703bf4a8f41c410
nightly-2022-10-16

Backtrace

Backtrace

<backtrace>

@skyzh skyzh added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Oct 23, 2022
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Oct 23, 2022
@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

Probably also related to RPITIT, as we make a intensive use of zero-overhead async trait with GAT:

impl<I: HummockIterator> MergeIteratorNext for OrderedMergeIteratorInner<I> {
    type HummockResultFuture<'a> = impl Future<Output = HummockResult<()>> + 'a;

    fn next_inner(&mut self) -> Self::HummockResultFuture<'_> {
        self.next_inner_inner()
    }
}

@compiler-errors
Copy link
Member

compiler-errors commented Oct 23, 2022

I don't think #102651 changed behavior at all, but cc @oli-obk 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.

@compiler-errors compiler-errors added E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc I-compiletime Issue: Problems and improvements with respect to compile times. labels Oct 23, 2022
@compiler-errors
Copy link
Member

I wonder if this was due to #100980.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

I’ll do a bisect tomorrow 🤣

@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

... but probably will take more time. #100980 is merged before #102700 which fixes a compiler bug. I'll need to bypass #101750 before bisecting into that date.

@compiler-errors
Copy link
Member

It's probably possible to just revert 43119d6 and check if that makes the program no longer slow to compile.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

Yeah no prob, I'll have a try.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

I reverted 43119d6 over latest master 6e95b6d and it worked perfectly 🤣 Thanks!

@compiler-errors
Copy link
Member

compiler-errors commented Oct 23, 2022

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 #100980 is incomplete.

@compiler-errors compiler-errors added E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example and removed E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc labels Oct 23, 2022
@skyzh
Copy link
Contributor Author

skyzh commented Oct 23, 2022

you mean the slowness is gone

Yes. It compiles within 2 minutes. Previously it seems never end, I wait at least 5 minutes before killing cargo.

this issue probably needs minimization and I can then look at why the fix in #100980 is incomplete.

Sure, I'll try minimizing it. From the PR description it sounds like a generator issue? I'll try combining futures_async_stream with some complex types, which should reflect how our code work.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 24, 2022

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.

@compiler-errors
Copy link
Member

Thanks so much for looking into this. I might also investigate, but I'm quite busy 😓

@skyzh
Copy link
Contributor Author

skyzh commented Oct 24, 2022

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.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 24, 2022

No prob, just wait until I got a minimum reproducible code, and it would be more efficient for you to look into 🤣

@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Oct 24, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Oct 24, 2022

Should we revert before the beta cutoff and try again? The diff isn't very complex after all

@skyzh
Copy link
Contributor Author

skyzh commented Oct 25, 2022

Though might be fixed by #103509, I'll probably still look into this and make a mcve based on the reverted commit.

@compiler-errors
Copy link
Member

It would be very useful if you created an MCVE that demonstrates the regression, for a future attempt to fix it. Thanks @skyzh.

@skyzh
Copy link
Contributor Author

skyzh commented Oct 27, 2022

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:

#![feature(generators)]
#![feature(trait_alias)]
#![feature(type_alias_impl_trait)]

use std::{borrow::Cow, convert::Infallible};

use futures::{executor::block_on, pin_mut, Future, Stream, StreamExt};
use futures_async_stream::stream;

pub trait AsyncIterator: 'static {
    type NextFuture<'a>: Future<Output = Result<(), Infallible>> + 'a
    where
        Self: 'a;

    fn next(&mut self) -> Self::NextFuture<'_>;
}

pub struct GoodIterator;

impl AsyncIterator for GoodIterator {
    type NextFuture<'a> = impl Future<Output = Result<(), Infallible>> + 'a;
    fn next(&mut self) -> Self::NextFuture<'_> {
        async move { futures::future::pending().await }
    }
}

pub struct BadIterator<const T: usize, I: AsyncIterator> {
    children: Vec<I>,
}

impl<const T: usize, I: AsyncIterator> BadIterator<T, I> {
    pub fn new(children: Vec<I>) -> Self {
        Self { children }
    }
}

impl<const T: usize, I: AsyncIterator> AsyncIterator for BadIterator<T, I> {
    type NextFuture<'a> = impl Future<Output = Result<(), Infallible>> + 'a;
    fn next(&mut self) -> Self::NextFuture<'_> {
        async move {
            for i in self.children.iter_mut() {
                i.next().await?;
            }
            Ok(())
        }
    }
}

pub enum IteratorUnion<I1: AsyncIterator, I2: AsyncIterator, I3: AsyncIterator, I4: AsyncIterator> {
    I1(I1),
    I2(I2),
    I3(I3),
    I4(I4),
}

impl<I1: AsyncIterator, I2: AsyncIterator, I3: AsyncIterator, I4: AsyncIterator> AsyncIterator
    for IteratorUnion<I1, I2, I3, I4>
{
    type NextFuture<'a> = impl Future<Output = Result<(), Infallible>> + 'a;
    fn next(&mut self) -> Self::NextFuture<'_> {
        async move {
            match self {
                Self::I1(x) => x.next().await,
                Self::I2(x) => x.next().await,
                Self::I3(x) => x.next().await,
                Self::I4(x) => x.next().await,
            }
        }
    }
}

fn create_iterator<const D: usize>() -> impl AsyncIterator {
    let iter1 = IteratorUnion::I1(BadIterator::<D, _>::new(vec![GoodIterator, GoodIterator]));
    let iter2 = IteratorUnion::I2(BadIterator::<D, _>::new(vec![GoodIterator, GoodIterator]));
    let iter3 = IteratorUnion::I3(BadIterator::<D, _>::new(vec![GoodIterator, GoodIterator]));
    let iter4 = IteratorUnion::I4(BadIterator::<D, _>::new(vec![GoodIterator, GoodIterator]));
    BadIterator::<233, _>::new(vec![iter1, iter2, iter3, iter4])
}

fn create_iterator_2<const D: usize>() -> impl AsyncIterator {
    let iter1 = IteratorUnion::I1(create_iterator::<1>());
    let iter2 = IteratorUnion::I2(create_iterator::<2>());
    let iter3 = IteratorUnion::I3(create_iterator::<3>());
    let iter4 = IteratorUnion::I4(create_iterator::<4>());
    BadIterator::<D, _>::new(vec![iter1, iter2, iter3, iter4])
}

fn create_iterator_3<const D: usize>() -> impl AsyncIterator {
    let iter1 = IteratorUnion::I1(create_iterator_2::<1>());
    let iter2 = IteratorUnion::I2(create_iterator_2::<2>());
    let iter3 = IteratorUnion::I3(create_iterator_2::<3>());
    let iter4 = IteratorUnion::I4(create_iterator_2::<4>());
    BadIterator::<D, _>::new(vec![iter1, iter2, iter3, iter4])
}

fn create_iterator_4<const D: usize>() -> impl AsyncIterator {
    let iter1 = IteratorUnion::I1(create_iterator_3::<1>());
    let iter2 = IteratorUnion::I2(create_iterator_3::<2>());
    let iter3 = IteratorUnion::I3(create_iterator_3::<3>());
    let iter4 = IteratorUnion::I4(create_iterator_3::<4>());
    BadIterator::<D, _>::new(vec![iter1, iter2, iter3, iter4])
}

fn create_iterator_5<const D: usize>() -> impl AsyncIterator {
    let iter1 = IteratorUnion::I1(create_iterator_4::<1>());
    let iter2 = IteratorUnion::I2(create_iterator_4::<2>());
    let iter3 = IteratorUnion::I3(create_iterator_4::<3>());
    let iter4 = IteratorUnion::I4(create_iterator_4::<4>());
    BadIterator::<D, _>::new(vec![iter1, iter2, iter3, iter4])
}

type MyFavoriteIterator = impl AsyncIterator;

fn create_iterator_6(x: usize) -> MyFavoriteIterator {
    create_iterator_4::<23333>()
}

#[stream(item = (Cow<'a, ()>, Cow<'a, ()>))]
async fn next<'a>(mut i: impl AsyncIterator) {
    loop {
        match i.next().await {
            Ok(_) => {}
            Err(_) => {}
        }
        yield (Cow::Owned(()), Cow::Owned(()));
    }
}

#[stream(item = (Cow<'a, ()>, Cow<'a, ()>))]
async fn next2<'a, S1, S2>( s1: S1,  s2: S2)
where
    S1: Stream<Item = (Cow<'a, ()>, Cow<'a, ()>)> + 'a,
    S2: Stream<Item = (Cow<'a, ()>, Cow<'a, ()>)>+ 'a,
{
    pin_mut!(s1);
    pin_mut!(s2);
    s1.next().await.unwrap();
    s2.next().await.unwrap();
}

macro_rules! repeat {
    ($x:expr) => ();
    ($x:expr, $($y:expr),+) => {
        block_on(async {
            let iter1 = create_iterator_6(1);
            let iter1 = next(iter1);
            let iter2 = create_iterator_6(1);
            let iter2 = next(iter2);
            let iter = next2(iter1, iter2);
            pin_mut!(iter);
            while let Some(_) = iter.next().await {}
        });
        repeat!($($y),+);
    };
}
fn main() {
    repeat!(
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1
    );
}

Basically, we are doing 3 things here:

  • Firstly, construct a complex nested iterator type, this will generate 5000 obligations on all call sites of next.
  • Secondly, construct next and next2 streams.
  • Then, generate repeat calls of next2.

On 758f196 (some commit on main), compiler will stuck. On nightly-2022-07-29 and #103509, this works perfectly,

Interestingly, without next2 function, e.g., change L144 to like

        block_on(async {
            let iter1 = create_iterator_6(1);
            let iter1 = next(iter1);
            pin_mut!(iter1);
            while let Some(_) = iter1.next().await {}
        });

None of them will stuck.

Therefore, I guess there's problem with next2 function's lifetime?

@skyzh
Copy link
Contributor Author

skyzh commented Oct 27, 2022

What's more interesting, change next2's signature to: This cannot be reproduced stably. Ignore this comment.

#[stream(item = (Cow<'a, ()>, Cow<'a, ()>))]
async fn next2<'a, S>(s1: S, s2: S)
where
    S: Stream<Item = (Cow<'a, ()>, Cow<'a, ()>)> + 'static,
{
    pin_mut!(s1);
    pin_mut!(s2);
    s1.next().await.unwrap();
    s2.next().await.unwrap();
}

will ICE on 758f196 (some commit on main)

@skyzh
Copy link
Contributor Author

skyzh commented Oct 27, 2022

Cargo.toml

[package]
name = "xxx"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
futures = "0.3"
futures-async-stream = { git = "https://github.com/taiki-e/futures-async-stream" }

@skyzh
Copy link
Contributor Author

skyzh commented Oct 30, 2022

I found a more simplified MCVE when workaround this bug in the codebase, without futures-async-stream. Trying to construct it...

@compiler-errors
Copy link
Member

@skyzh do you have a branch of the full risingwave project that I can test the regression on?

@skyzh

This comment was marked as outdated.

@skyzh

This comment was marked as outdated.

@skyzh
Copy link
Contributor Author

skyzh commented Nov 7, 2022

Okay, I probably did the compile in a wrong way. Testing again, sorry for that 🙈

@skyzh
Copy link
Contributor Author

skyzh commented Nov 7, 2022

Here's what I did:

rustup update nightly # so that we can use latest version of cargo
./x.py build --stage 1
rustup toolchain link stage1 build/aarch64-apple-darwin/stage1
CARGO_TARGET_DIR=target/stage1 cargo +stage1 build -p risingwave_stream

Unluckily, https://github.com/compiler-errors/rust/tree/issue-103423 doesn't seem to fix the issue. The rustc process keeps spinning at 100% CPU and seems never to complete when compiling risingwave_stream 🙈

@skyzh
Copy link
Contributor Author

skyzh commented Nov 7, 2022

@bors bors closed this as completed in 5e6de23 Nov 19, 2022
Aaron1011 pushed a commit to Aaron1011/rust that referenced this issue Jan 6, 2023
…-r-hard, r=oli-obk

Revert "Normalize opaques with escaping bound vars"

This caused a perf regression in rust-lang#103423, cc `@skyzh` this should fix rust-lang#103423.

reverts rust-lang#100980

r? `@oli-obk`
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 29, 2023
…th-late-bound-vars-again, r=jackh726

Normalize opaques with late-bound vars again

We have a hack in the compiler where if an opaque has escaping late-bound vars, we skip revealing it even though we *could* reveal it from a technical perspective. First of all, this is weird, since we really should be revealing all opaques in `Reveal::All` mode. Second of all, it causes subtle bugs (linked below).

I attempted to fix this in rust-lang#100980, which was unfortunately reverted due to perf regressions on codebases that used really deeply nested futures in some interesting ways. The worst of which was rust-lang#103423, which caused the project to hang on build. Another one was rust-lang#104842, which was just a slow-down, but not a hang. I took some time afterwards to investigate how to rework `normalize_erasing_regions` to take advantage of better caching, but that effort kinda fizzled out (rust-lang#104133).

However, recently, I was made aware of more bugs whose root cause is not revealing opaques during codegen. That made me want to fix this again -- in the process, interestingly, I took the the minimized example from rust-lang#103423 (comment), and it doesn't seem to hang any more...

Thinking about this harder, there have been some changes to the way we lower and typecheck async futures that may have reduced the pathologically large number of outlives obligations (see description of rust-lang#103423) that we were encountering when normalizing opaques with bound vars the last time around:
* rust-lang#104321 (lower `async { .. }` directly as a generator that implements `Future`, removing the `from_generator` shim)
* rust-lang#104833 (removing an `identity_future` fn that was wrapping desugared future generators)

... so given that I can see:
* No significant regression on rust perf bot (rust-lang#107620 (comment))
* No timeouts in crater run I did (rust-lang#107620 (comment), rechecked failing crates in rust-lang#107620 (comment))

... and given that this PR:
* Fixes rust-lang#104601
* Fixes rust-lang#107557
* Fixes rust-lang#109464
* Allows us to remove a `DefiningAnchor::Bubble` from codegen (75a8f68)

I'm inclined to give this another shot at landing this. Best case, it just works -- worst case, we get more examples to study how we need to improve the compiler to make this work.

r? types
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Jul 2, 2023
…ound-vars-again, r=jackh726

Normalize opaques with late-bound vars again

We have a hack in the compiler where if an opaque has escaping late-bound vars, we skip revealing it even though we *could* reveal it from a technical perspective. First of all, this is weird, since we really should be revealing all opaques in `Reveal::All` mode. Second of all, it causes subtle bugs (linked below).

I attempted to fix this in #100980, which was unfortunately reverted due to perf regressions on codebases that used really deeply nested futures in some interesting ways. The worst of which was #103423, which caused the project to hang on build. Another one was #104842, which was just a slow-down, but not a hang. I took some time afterwards to investigate how to rework `normalize_erasing_regions` to take advantage of better caching, but that effort kinda fizzled out (#104133).

However, recently, I was made aware of more bugs whose root cause is not revealing opaques during codegen. That made me want to fix this again -- in the process, interestingly, I took the the minimized example from rust-lang/rust#103423 (comment), and it doesn't seem to hang any more...

Thinking about this harder, there have been some changes to the way we lower and typecheck async futures that may have reduced the pathologically large number of outlives obligations (see description of #103423) that we were encountering when normalizing opaques with bound vars the last time around:
* #104321 (lower `async { .. }` directly as a generator that implements `Future`, removing the `from_generator` shim)
* #104833 (removing an `identity_future` fn that was wrapping desugared future generators)

... so given that I can see:
* No significant regression on rust perf bot (rust-lang/rust#107620 (comment))
* No timeouts in crater run I did (rust-lang/rust#107620 (comment), rechecked failing crates in rust-lang/rust#107620 (comment))

... and given that this PR:
* Fixes #104601
* Fixes #107557
* Fixes #109464
* Allows us to remove a `DefiningAnchor::Bubble` from codegen (75a8f681837c70051e0200a14f58ae07dbe58e66)

I'm inclined to give this another shot at landing this. Best case, it just works -- worst case, we get more examples to study how we need to improve the compiler to make this work.

r? types
lnicola pushed a commit to lnicola/rust-analyzer that referenced this issue Apr 7, 2024
…ound-vars-again, r=jackh726

Normalize opaques with late-bound vars again

We have a hack in the compiler where if an opaque has escaping late-bound vars, we skip revealing it even though we *could* reveal it from a technical perspective. First of all, this is weird, since we really should be revealing all opaques in `Reveal::All` mode. Second of all, it causes subtle bugs (linked below).

I attempted to fix this in #100980, which was unfortunately reverted due to perf regressions on codebases that used really deeply nested futures in some interesting ways. The worst of which was #103423, which caused the project to hang on build. Another one was #104842, which was just a slow-down, but not a hang. I took some time afterwards to investigate how to rework `normalize_erasing_regions` to take advantage of better caching, but that effort kinda fizzled out (#104133).

However, recently, I was made aware of more bugs whose root cause is not revealing opaques during codegen. That made me want to fix this again -- in the process, interestingly, I took the the minimized example from rust-lang/rust#103423 (comment), and it doesn't seem to hang any more...

Thinking about this harder, there have been some changes to the way we lower and typecheck async futures that may have reduced the pathologically large number of outlives obligations (see description of #103423) that we were encountering when normalizing opaques with bound vars the last time around:
* #104321 (lower `async { .. }` directly as a generator that implements `Future`, removing the `from_generator` shim)
* #104833 (removing an `identity_future` fn that was wrapping desugared future generators)

... so given that I can see:
* No significant regression on rust perf bot (rust-lang/rust#107620 (comment))
* No timeouts in crater run I did (rust-lang/rust#107620 (comment), rechecked failing crates in rust-lang/rust#107620 (comment))

... and given that this PR:
* Fixes #104601
* Fixes #107557
* Fixes #109464
* Allows us to remove a `DefiningAnchor::Bubble` from codegen (75a8f681837c70051e0200a14f58ae07dbe58e66)

I'm inclined to give this another shot at landing this. Best case, it just works -- worst case, we get more examples to study how we need to improve the compiler to make this work.

r? types
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 27, 2024
…ound-vars-again, r=jackh726

Normalize opaques with late-bound vars again

We have a hack in the compiler where if an opaque has escaping late-bound vars, we skip revealing it even though we *could* reveal it from a technical perspective. First of all, this is weird, since we really should be revealing all opaques in `Reveal::All` mode. Second of all, it causes subtle bugs (linked below).

I attempted to fix this in #100980, which was unfortunately reverted due to perf regressions on codebases that used really deeply nested futures in some interesting ways. The worst of which was #103423, which caused the project to hang on build. Another one was #104842, which was just a slow-down, but not a hang. I took some time afterwards to investigate how to rework `normalize_erasing_regions` to take advantage of better caching, but that effort kinda fizzled out (#104133).

However, recently, I was made aware of more bugs whose root cause is not revealing opaques during codegen. That made me want to fix this again -- in the process, interestingly, I took the the minimized example from rust-lang/rust#103423 (comment), and it doesn't seem to hang any more...

Thinking about this harder, there have been some changes to the way we lower and typecheck async futures that may have reduced the pathologically large number of outlives obligations (see description of #103423) that we were encountering when normalizing opaques with bound vars the last time around:
* #104321 (lower `async { .. }` directly as a generator that implements `Future`, removing the `from_generator` shim)
* #104833 (removing an `identity_future` fn that was wrapping desugared future generators)

... so given that I can see:
* No significant regression on rust perf bot (rust-lang/rust#107620 (comment))
* No timeouts in crater run I did (rust-lang/rust#107620 (comment), rechecked failing crates in rust-lang/rust#107620 (comment))

... and given that this PR:
* Fixes #104601
* Fixes #107557
* Fixes #109464
* Allows us to remove a `DefiningAnchor::Bubble` from codegen (75a8f681837c70051e0200a14f58ae07dbe58e66)

I'm inclined to give this another shot at landing this. Best case, it just works -- worst case, we get more examples to study how we need to improve the compiler to make this work.

r? types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-compiletime Issue: Problems and improvements with respect to compile times. P-high High priority regression-untriaged Untriaged performance or correctness regression.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants