Skip to content

[ICE]: "did not expect successful goal when collecting ambiguity errors" #162557

Closed

Description

@conradoplg

We're hitting an ICE while running cargo doc in your CI.

The following is Claude-generated; it contains the steps to reproduce it and some analysis.


Summary

Since nightly-2026-09-08, cargo doc on the Zebra
workspace ICEs while documenting zebra-consensus. rustdoc's auto-trait/blanket-impl synthesis
calls InferCtxt::evaluate_obligation, which goes through
FulfillmentEngine<ScrubbedTraitError>::evaluate_obligations_error_on_ambiguity. A stalled
OutlivesClause(<Verifier as Service<BatchControl<Item>>>::Future, 'static) goal then re-evaluates
to Certainty::Yes, tripping the span_delayed_bug in
compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:140.

This is rustdoc-only: cargo check on the same commit and the same toolchain succeeds.

Reproduced locally on 1.100.0-nightly (4aa1fbcf4 2026-09-08) as well as in CI.

Steps to reproduce

git init zebra-ice && cd zebra-ice
git remote add origin https://github.com/ZcashFoundation/zebra.git
git fetch --depth=1 origin abf397469356dd03f7e6321a33b41f0d98a20060
git checkout --detach FETCH_HEAD

# ICEs
cargo +nightly doc --no-deps -p zebra-consensus --all-features --document-private-items

# For contrast, this succeeds on the same toolchain and commit
cargo +nightly check -p zebra-consensus --all-features

abf397469356dd03f7e6321a33b41f0d98a20060 is a commit on Zebra's main; the failure reproduces on
current main too. Note that Zebra's rust-toolchain.toml pins a stable toolchain, so the
+nightly override is required.

Building the whole workspace, as our CI does, hits the same ICE:

cargo +nightly doc --no-deps --workspace --all-features --document-private-items

Zebra vendors a C++ dependency (rocksdb) via librocksdb-sys. On a host with GCC 15 the build
needs CXXFLAGS="-include cstdint"; this is unrelated to the ICE but is needed to get far enough
to hit it.

Public CI logs

The failure is reproducible in public CI, which runs the floating nightly channel:

Meta

rustc 1.100.0-nightly (4aa1fbcf4 2026-09-08)
binary: rustc
commit-hash: 4aa1fbcf467cf38ce58abfa8eb9213a789c5381c
commit-date: 2026-09-08
host: x86_64-unknown-linux-gnu
release: 1.100.0-nightly
LLVM version: 23.1.1

Also reproduces on rustc 1.100.0-nightly (cea272fa3 2026-09-07).

Error output

12 delayed bugs are emitted, over 7 distinct goals. All of them are
OutlivesClause(<_ as tower_service::Service<_>>::Future, 'static):

error: internal compiler error: did not expect successful goal when collecting ambiguity errors for `Binder { value: OutlivesClause(Alias(No, Alias { kind: Projection { def_id: DefId(42:11 ~ tower_service[ee0b]::Service::Future) }, args: [primitives::ed25519::Verifier, tower_batch_control::BatchControl<primitives::ed25519::Item>], .. }), 'static), bound_vars: [] }`

The other six differ only in args:

[primitives::halo2::OrchardFallback,   primitives::halo2::Item]
[primitives::halo2::Verifier,          tower_batch_control::BatchControl<primitives::halo2::Item>]
[primitives::redjubjub::Verifier,      tower_batch_control::BatchControl<primitives::redjubjub::Item>]
[primitives::redpallas::Verifier,      tower_batch_control::BatchControl<primitives::redpallas::Item>]
[primitives::sapling::Verifier,        tower_batch_control::BatchControl<primitives::sapling::Item>]
[script::Verifier,                     script::Request]

followed by (no special RUSTDOCFLAGS are involved — this is a plain cargo doc):

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md
note: please make sure that you have updated to the latest nightly
note: rustc 1.100.0-nightly (cea272fa3 2026-09-07) running on x86_64-unknown-linux-gnu
note: compiler flags: --crate-type lib
note: some of the compiler flags provided by cargo are hidden
query stack during panic:
end of query stack
error: could not document `zebra-consensus`
Backtrace

  = note: delayed at /rustc-dev/4aa1fbcf467cf38ce58abfa8eb9213a789c5381c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:140:29
             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_trait_selection::solve::fulfill::collect_remaining_errors_impl::<rustc_infer::traits::engine::ScrubbedTraitError>
             5: <rustc_trait_selection::traits::engine::FulfillmentEngine<rustc_infer::traits::engine::ScrubbedTraitError> as rustc_infer::traits::engine::TraitEngine<rustc_infer::traits::engine::ScrubbedTraitError>>::evaluate_obligations_error_on_ambiguity
             6: <rustc_infer::infer::InferCtxt as rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation
             7: rustdoc::clean::utils::synthesize_auto_trait_and_blanket_impls
             8: <rustdoc::passes::collect_trait_impls::SyntheticImplCollector as rustdoc::visit::DocVisitor>::visit_item
             9: <rustdoc::passes::collect_trait_impls::SyntheticImplCollector as rustdoc::visit::DocVisitor>::visit_item
            10: <rustdoc::passes::collect_trait_impls::SyntheticImplCollector as rustdoc::visit::DocVisitor>::visit_item
            11: <rustdoc::passes::collect_trait_impls::SyntheticImplCollector as rustdoc::visit::DocVisitor>::visit_item
            12: <rustc_session::session::Session>::time::<rustdoc::clean::types::Crate, rustdoc::passes::run::{closure#0}>
            13: rustdoc::core::run_global_ctxt
            14: rustdoc::main_args::{closure#2}::{closure#0}
            15: rustc_interface::interface::run_compiler::<(), rustdoc::main_args::{closure#2}>::{closure#2}
            16: 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<(), rustdoc::main_args::{closure#2}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
            17: <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<(), rustdoc::main_args::{closure#2}>::{closure#2}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
            18: <std::sys::thread::unix::Thread>::new::thread_start
            19: <unknown>
            20: <unknown>

The rustc-ice-*.txt file the diagnostic points at contains only the version and platform lines —
these are span_delayed_bugs rather than a panic, so there is no panic backtrace to attach beyond
the one above.

Suspected cause

Regression window from our CI, which tracks floating nightly:

nightly channel rustc result
nightly-2026-09-04 a69a63265 2026-09-03 ok
nightly-2026-09-08 cea272fa3 2026-09-07 ICE
nightly-2026-09-09 4aa1fbcf4 2026-09-08 ICE

That window contains #162182 ("delay unexpected successful goal during ambiguity reporting",
merged as 29c965e): the last good nightly is an ancestor of 29c965e, and the first bad one is
77 commits after it.

Reading that diff, the mechanism looks like this. Before #162182, the re-evaluation of stalled
obligations lived in fulfillment_error_for_stalled, which is only reached from
FromSolverError::from_solver_error for FulfillmentError. ScrubbedTraitError has its own
FromSolverError impl that maps NextSolverError::Ambiguity straight to
ScrubbedTraitError::Ambiguity without re-evaluating, so rustdoc never took that path. #162182
moved the re-evaluation eagerly into collect_remaining_errors_impl, which is generic over the
error type and therefore now runs for ScrubbedTraitError too — which is exactly what frames 4-6
of the backtrace show.

If that reading is right, #162182 didn't introduce the underlying "stalled goal re-evaluates to
Certainty::Yes" condition; it made a new caller (rustdoc) able to observe it.

Shape of the triggering code

The goals all come from documenting zebra_consensus::primitives::*, which declare public statics
of roughly this shape (source):

pub static VERIFIER: Lazy<
    Fallback<
        Batch<Verifier, Item>,
        ServiceFn<fn(Item) -> BoxFuture<'static, Result<(), BoxError>>>,
    >,
> = Lazy::new(|| { /* ... */ });

where tower_batch_control::Batch stores the associated future in a channel
(source):

pub struct Batch<T, Request: RequestWeight>
where
    T: Service<BatchControl<Request>>,
{
    tx: mpsc::UnboundedSender<Message<Request, T::Future>>,
    // ...
}

so auto-trait synthesis on Fallback<Batch<Verifier, Item>, _> has to prove
<Verifier as Service<BatchControl<Item>>>::Future: 'static.

I have not managed to reduce this to a standalone file — a hand-written skeleton with the same
struct shapes does not ICE, so something in the surrounding tower / tower-batch-control bounds
is needed to make the goal stall in the first place. Happy to run cargo-bisect-rustc or try
further minimization if that would help.

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 Sep 9, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Sep 9, 2026
  3. Adarsh-Me commented on Sep 10, 2026

    @Adarsh-Me
  4. bb1yd commented on Sep 10, 2026

    @bb1yd
  5. rustbot commented on Sep 10, 2026

    @rustbot
  6. Adarsh-Me commented on Sep 10, 2026

    @Adarsh-Me
  7. rustbot commented on Sep 10, 2026

    @rustbot
  8. theemathas commented on Sep 10, 2026

    @theemathas
  9. ShoyuVanilla commented on Sep 11, 2026

    @ShoyuVanilla
    Member

    @Adarsh-Me we've been discussing about this on zulip and I think this needs some context a bit. So I'm gonna assign this to myself as it's not technically claimed, though you intended to do so 😅 , sorry. Ping me if you want to work on this regarding the mentioned zulip topic

    @rustbot claim

  10. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Sep 13, 2026
  11. added 4 commits that reference this issue on Oct 1, 2026
    26cc99d
    31c03c5
    6e4fa3d
    0d66027
  12. added a commit that references this issue on Oct 2, 2026
    4f8baea
  13. added a commit that references this issue on Oct 6, 2026
    90ef3f8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.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.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions