rust-lang / rust

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

`Failed to normalize` `async_fn_in_trait` ICE for indirect recursion of async trait method calls #112047

Closed rkusa closed 1 year ago

rkusa commented 1 year ago

The following happens for the async_fn_in_trait feature. I guess it is caused by the indirect recursion (First::first() -> Second::second() -> First::first() -> Second::second() -> First::first() -> ...).

Code

#![feature(async_fn_in_trait)]

fn main() {
    let _ = async {
        A.first().await.second().await;
    };
}

pub trait First {
    type Second: Second;
    async fn first(self) -> Self::Second;
}

struct A;

impl First for A {
    type Second = A;
    async fn first(self) -> Self::Second {
        A
    }
}

pub trait Second {
    async fn second(self);
}

impl<C> Second for C
where
    C: First,
{
    async fn second(self) {
        self.first().await.second().await;
    }
}

Meta

rustc --version --verbose:

rustc 1.71.0-nightly (cca7ee581 2023-05-27)
binary: rustc
commit-hash: cca7ee58110726983951a19d5fb7316d9243925d
commit-date: 2023-05-27
host: aarch64-apple-darwin
release: 1.71.0-nightly
LLVM version: 16.0.4

Error output

error: internal compiler error: compiler/rustc_middle/src/ty/normalize_erasing_regions.rs:195:90: Failed to normalize [async block@src/main.rs:4:13: 6:6], maybe try to call `try_normalize_erasing_regions` instead
Backtrace

``` thread 'rustc' panicked at 'Box', /rustc/cca7ee58110726983951a19d5fb7316d9243925d/compiler/rustc_errors/src/lib.rs:1651:9 stack backtrace: 0: std::panicking::begin_panic:: 1: ::bug:: 2: ::bug:: 3: rustc_middle::util::bug::opt_span_bug_fmt::::{closure#0} 4: rustc_middle::ty::context::tls::with_opt::::{closure#0}, !>::{closure#0} 5: rustc_middle::ty::context::tls::with_context_opt::::{closure#0}, !>::{closure#0}, !> 6: rustc_middle::util::bug::bug_fmt 7: >::fold_ty 8: ::visit_terminator 9: rustc_monomorphize::collector::collect_neighbours 10: rustc_monomorphize::collector::collect_items_rec 11: , rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure#0}>::{closure#0}::{closure#0}> as core::ops::function::FnOnce<()>>::call_once 12: rustc_data_structures::sync::par_for_each_in::, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure#0}> 13: ::time::<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}> 14: rustc_monomorphize::collector::collect_crate_mono_items 15: rustc_monomorphize::partitioning::collect_and_partition_mono_items 16: rustc_codegen_ssa::base::codegen_crate:: 17: ::codegen_crate 18: rustc_interface::passes::start_codegen 19: ::enter::<::ongoing_codegen::{closure#0}::{closure#0}, core::result::Result, rustc_span::ErrorGuaranteed>> 20: ::ongoing_codegen 21: ::enter::, rustc_span::ErrorGuaranteed>> 22: rustc_span::set_source_map::, rustc_interface::interface::run_compiler, rustc_driver_impl::run_compiler::{closure#1}>::{closure#0}::{closure#0}> 23: >::set::, rustc_driver_impl::run_compiler::{closure#1}>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>> note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: rustc 1.71.0-nightly (cca7ee581 2023-05-27) running on aarch64-apple-darwin note: compiler flags: --crate-type bin -C embed-bitcode=no -C split-debuginfo=unpacked -C debuginfo=2 -C incremental=[REDACTED] note: some of the compiler flags provided by cargo are hidden query stack during panic: #0 [collect_and_partition_mono_items] collect_and_partition_mono_items end of query stack ```

matthiaskrgr commented 1 year ago

Regression in nightly-2022-09-24

compiler-errors commented 1 year ago

This is reproducible with type alias impl trait (well, impl trait in assoc ty) similarly:

#![feature(impl_trait_in_assoc_type)]

use core::future::Future;

trait Recur {
    type Recur: Future<Output = ()>;

    fn recur(self) -> Self::Recur;
}

async fn recur(t: impl Recur) {
    t.recur().await;
}

impl Recur for () {
    type Recur = impl Future<Output = ()>;

    fn recur(self) -> Self::Recur {
        async move { recur(self).await; }
    }
}

fn main() {
    recur(());
}

I consider this to be somewhat concerning, because both of these features introduce a new kind of post-monomorphization error that (afaict) can't be reproduced with associated types on stable rust.