Skip to content

ICE: Creating trait object of wrapper struct of a async closure with non-generic arugment and generic arguments with multiple allowed arities #147719

Open

Description

@vivax3794

edit(@lcnr): minimized regression test added in #163806

//@ revisions: old next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[old] failure-status: 101
//@[old] dont-check-compiler-stderr
//@[old] known-bug: #147719
//@ edition: 2024

// A variant of `old-solver-only-leak-check-on-ambig.rs` which
// relies on us deferring the inference of async closure upvars.
// `Fut` is higher ranked as it ends up capturing the function
// argument.

struct Wrap<F>(F);
trait NotImplemented {}
trait NodeImpl {}
impl<T: NotImplemented> NodeImpl for T {}
impl<F, Fut> NodeImpl for Wrap<F>
where
    F: Fn(&()) -> Fut,
{
}

fn node_impl<T: NodeImpl>(_: T) {}
fn main() {
    node_impl(Wrap(async |_: &()| ()));
    //[next]~^ ERROR: the trait bound
}

Code

use std::marker::PhantomData;

struct RuntimeContext {}

pub trait NodeImpl {}

struct Wrap<F, P>(F, PhantomData<P>);

impl<F, P> Wrap<F, P> {
    fn new(func: F) -> Self {
        Self(func, PhantomData)
    }
}

trait Arg {}
impl Arg for i128 {}

impl<F, Fut, A> NodeImpl for Wrap<F, A>
where
    F: Fn(&RuntimeContext, A) -> Fut,
    Fut: Future<Output = i128>,
    A: Arg,
{
}

impl<F, Fut, A, B> NodeImpl for Wrap<F, (A, B)>
where
    F: Fn(&RuntimeContext, A, B) -> Fut,
    Fut: Future<Output = i128>,
    A: Arg,
    B: Arg,
{
}

pub fn trigger_ice() {
    let x: Box<dyn NodeImpl> = Box::new(Wrap::<_, (i128, i128)>::new(
        async |_context: &RuntimeContext, x: i128, y: i128| 10,
    ));
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=52a3b870e6d97bb25cbb3279074618e5

Meta

rustc --version --verbose:

rustc 1.92.0-nightly (844264add 2025-10-14)
binary: rustc
commit-hash: 844264adda6f41ca6d0d61c4bcac0f263fc5072f
commit-date: 2025-10-14
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.3

Error output

note: no errors encountered even though delayed bugs were created

note: those delayed bugs will now be shown as internal compiler errors

error: internal compiler error: error performing operation: fully_perform
  --> src/lib.rs:36:32
   |
36 |       let x: Box<dyn NodeImpl> = Box::new(Wrap::<_, (i128, i128)>::new(
   |  ________________________________^
37 | |         async |_context: &RuntimeContext, x: i128, y: i128| 10,
38 | |     ));
   | |______^
   |
note: delayed at /rustc-dev/4b94758d2ba7d0ef71ccf5fde29ce4bc5d6fe2a4/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs:95:25
  --> src/lib.rs:36:32
   |
36 |       let x: Box<dyn NodeImpl> = Box::new(Wrap::<_, (i128, i128)>::new(
   |  ________________________________^
37 | |         async |_context: &RuntimeContext, x: i128, y: i128| 10,
38 | |     ));
   | |______^

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: please make sure that you have updated to the latest nightly

note: please attach the file at `/playground/rustc-ice-2025-10-15T09_32_10-46.txt` to your bug report

note: compiler flags: --crate-type lib -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2

note: some of the compiler flags provided by cargo are hidden
Backtrace

0: <rustc_errors::DiagCtxtInner>::emit_diagnostic
         1: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
         2: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
         3: <rustc_errors::DiagCtxtHandle>::span_delayed_bug::<rustc_span::span_encoding::Span, alloc::string::String>
         4: <rustc_borrowck::type_check::TypeChecker>::prove_trait_ref
         5: <rustc_borrowck::type_check::TypeChecker as rustc_middle::mir::visit::Visitor>::visit_rvalue
         6: <rustc_borrowck::type_check::TypeChecker as rustc_middle::mir::visit::Visitor>::visit_body
         7: rustc_borrowck::type_check::type_check
         8: <rustc_borrowck::root_cx::BorrowCheckRootCtxt>::do_mir_borrowck
         9: rustc_borrowck::mir_borrowck
        10: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_borrowck::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 8]>>
        11: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::Erased<[u8; 8]>, rustc_query_system::dep_graph::graph::DepNodeIndex>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        12: rustc_query_impl::query_impl::mir_borrowck::get_query_non_incr::__rust_end_short_backtrace
        13: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface::passes::run_required_analyses::{closure#1}::{closure#0}>::{closure#0}
        14: rustc_interface::passes::analysis
        15: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle::query::erase::Erased<[u8; 0]>>
        16: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::DynamicConfig<rustc_query_system::query::caches::SingleCache<rustc_middle::query::erase::Erased<[u8; 0]>>, false, false, false>, rustc_query_impl::plumbing::QueryCtxt, false>
        17: rustc_query_impl::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
        18: <rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2} as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, alloc::sync::Arc<rustc_data_structures::jobserver::Proxy>, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once::{shim:vtable#0}
        19: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
        20: std::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
        21: <<std::thread::Builder>::spawn_unchecked_<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
        22: std::sys::thread::unix::Thread::new::thread_start
        23: <unknown>
        24: clone

Activity

  1. added
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    on Oct 15, 2025
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Oct 15, 2025
  3. cyrgani commented on Oct 15, 2025

    @cyrgani
    Contributor

    a bit smaller:

    use std::marker::PhantomData;
    
    pub trait NodeImpl {}
    
    struct Wrap<F, P>(F, PhantomData<P>);
    
    impl<F, P> Wrap<F, P> {
        fn new(_: F) -> Self {
            loop {}
        }
    }
    
    trait Arg {}
    
    impl<F, A> NodeImpl for Wrap<F, A> where A: Arg {}
    
    impl<F, Fut, A> NodeImpl for Wrap<F, (A, )>
    where
        F: Fn(&(), A) -> Fut,
    {
    }
    
    pub fn trigger_ice() {
        let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(
            async |_: &(), _: i128| (),
        );
    }
  4. added
    S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue
    fixed-by-next-solverFixed by the next-generation trait solver, `-Znext-solver`.
    on Oct 15, 2025
  5. matthiaskrgr commented on Oct 15, 2025

    @matthiaskrgr
    Member

    auto-reduced

    trait NodeImpl {}
    struct Wrap<F, P>(F, P);
    impl<F, P> Wrap<F, P> {
        fn new(_: F) -> Self {
            loop {}
        }
    }
    trait Arg {}
    impl<F, A> NodeImpl for Wrap<F, A> where A: Arg {}
    impl<F, Fut, A> NodeImpl for Wrap<F, (A,)> where F: Fn(&(), A) -> Fut {}
    fn trigger_ice() {
        let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(async |_: &(), i128| 0);
    }
  6. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Dec 30, 2025
  7. added
    S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.
    on Jun 27, 2026
  8. added 3 commits that reference this issue on Oct 7, 2026
  9. added a commit that references this issue on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.fixed-by-next-solverFixed by the next-generation trait solver, `-Znext-solver`.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions