rust-lang / rust-lang/rust

[ICE]: broken MIR (`... NoSolution`) when a value with a `for<'a>` HRTB over a GAT is wrapped in a one-element array

Open
#158,648 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug fixed-by-next-solver I-ICE needs-triage T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Start from rustc's own UI test tests/ui/closures/closure-capture-hrtb-gat-no-ice-120811.rs (//@ check-pass, the regression test for #120811). Wrap the by-value unary_frontier argument exchange in a one-element array - unary_frontier([exchange]), with unary_frontier taking [P; 1]. The for<'a> HRTB-over-GAT bound is untouched. This causes an ICE:

trait Container { type Item<'a>; }
impl Container for () { type Item<'a> = (); }

struct Exchange<C, F> { _marker: std::marker::PhantomData<(C, F)> }

fn exchange<C, F>(_: F) -> Exchange<C, F>
where
    C: Container,
    for<'a> F: FnMut(&C::Item<'a>),
{ unimplemented!() }

trait Parallelization<C> {}
impl<C, F> Parallelization<C> for Exchange<C, F> {}

fn unary_frontier<P: Parallelization<()>>(_f: [P; 1]) { let [_p] = _f; }

fn main() {
    let exchange = exchange(|_| ());
    unary_frontier([exchange]);
}

Reproduces on stable, beta, and nightly; the seed (//@ check-pass) keeps compiling on all three:

channel version seed rewritten
stable 1.96.0 (ac68faa20 2026-05-25) compiles ICE
beta 1.97.0-beta.5 (c04e321a9 2026-06-26) compiles ICE
nightly 1.98.0-nightly (f46ec5218 2026-06-30) compiles ICE

(On nightly the unnormalized projection prints as Alias(No, Alias { kind: Projection { .. }, args: [(), '^1] }) rather than stable/beta's Alias(AliasTy { args: [(), '^1], kind: Projection { .. } }) - a Debug-format difference only.)

Meta
rustc 1.96.0 (ac68faa20 2026-05-25)
binary: rustc
commit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96
commit-date: 2026-05-25
host: aarch64-apple-darwin
release: 1.96.0
LLVM version: 22.1.2

Also reproduced on beta 1.97.0-beta.5 and nightly 1.98.0-nightly (f46ec5218 2026-06-30) (see the channel table above).

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: broken MIR in DefId(0:25 ~ main[8f81]::main) ([move _5]): Exchange<(), Closure(DefId(0:26 ~ main[8f81]::main::{closure#0}), [i16, Binder { value: extern "RustCall" fn((&'^0 (),)), bound_vars: [Region(BrAnon), Region(BrAnon)] }, ()])> is not a subtype of Exchange<(), Closure(DefId(0:26 ~ main[8f81]::main::{closure#0}), [i16, Binder { value: extern "RustCall" fn((&'^0 Alias(AliasTy { args: [(), '^1], kind: Projection { def_id: DefId(0:4 ~ main[8f81]::Container::Item) }, .. }),)), bound_vars: [Region(BrAnon), Region(BrAnon)] }, ()])>: NoSolution
  --> src/main.rs:19:20
   |
19 |     unary_frontier([exchange]);
   |                    ^^^^^^^^^^
   |
note: delayed at compiler/rustc_borrowck/src/type_check/mod.rs:2283:17
         0: <std::backtrace::Backtrace>::create
         1: <rustc_errors::DiagCtxtInner>::emit_diagnostic
         2: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
         3: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
         4: <rustc_errors::DiagCtxtHandle>::span_delayed_bug::<rustc_span::span_encoding::Span, alloc::string::String>
         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_statement
         7: <rustc_borrowck::type_check::TypeChecker as rustc_middle::mir::visit::Visitor>::visit_body
         8: rustc_borrowck::type_check::type_check
         9: rustc_borrowck::borrowck_collect_region_constraints
        10: <rustc_borrowck::root_cx::BorrowCheckRootCtxt>::do_mir_borrowck
        11: rustc_borrowck::mir_borrowck
        12: rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
        13: rustc_query_impl::query_impl::mir_borrowck::execute_query_non_incr::__rust_end_short_backtrace
        14: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
        15: rustc_interface::passes::analysis
        16: rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>, false>
        17: rustc_query_impl::query_impl::analysis::execute_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}>
        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::lifecycle::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: __pthread_cond_wait
      
  --> src/main.rs:19:20
   |
19 |     unary_frontier([exchange]);
   |                    ^^^^^^^^^^

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.96.0 (ac68faa20 2026-05-25) running on aarch64-apple-darwin

query stack during panic:
end of query stack
Backtrace

<backtrace>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with tests/ui/closures/closure-capture-hrtb-gat-no-ice-120811.rs and reproduce the array-wrapped variant from the issue. Read the borrow-checking path at compiler/rustc_borrowck/src/type_check/mod.rs, especially the reported delayed-bug location. Done means the reduced case no longer produces an ICE while the original check-pass test remains passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.