Skip to content

[ICE]: DynCompatible "should have been handled by fulfillment already" for return-position impl Trait #158656

Description

@gustavovalverde

Code

use std::future::Future;
use std::pin::Pin;

pub trait Service {
    type Future;
}

pub struct Concrete;
impl Service for Concrete {
    type Future = Pin<Box<dyn Future<Output = ()>>>;
}

pub fn make() -> impl Service<Future = impl Future<Output = ()>> {
    Concrete
}

The code compiles on stable 1.91.0 and on nightlies through 2026-06-29. It uses no unstable features.

Meta

rustc --version --verbose:

rustc 1.98.0-nightly (f46ec5218 2026-06-30)
binary: rustc
commit-hash: f46ec5218fe7829ac18323b5ee0b409a63169f27
commit-date: 2026-06-30
host: aarch64-apple-darwin
release: 1.98.0-nightly
LLVM version: 22.1.8

Error output

error: internal compiler error: compiler/rustc_trait_selection/src/traits/select/mod.rs:775:21: Obligation Obligation(predicate=Binder { value: DynCompatible(DefId(2:46104 ~ core::future::future::Future)), bound_vars: [] }, depth=2) should have been handled by fulfillment already.

query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `<Concrete as Service>::Future == make::{opaque#0}::{opaque#0}`
#1 [typeck_root] type-checking `make`
#2 [check_match] match-checking `make`
#3 [mir_built] building MIR for `make`
#4 [has_ffi_unwind_calls] checking if `make` contains FFI-unwind calls
#5 [mir_promoted] promoting constants in MIR for `make`
#6 [mir_borrowck] borrow-checking `make`
#7 [type_of_opaque] computing type of opaque `make::{opaque#0}`
#8 [type_of] computing type of `make::{opaque#0}`
#9 [check_well_formed] checking that `make::{opaque#0}` is well-formed
#10 [check_type_wf] checking that types are well-formed
#11 [analysis] running analysis passes on crate `min`
end of query stack
Backtrace

error: internal compiler error: compiler/rustc_trait_selection/src/traits/select/mod.rs:775:21: Obligation Obligation(predicate=Binder { value: DynCompatible(DefId(2:46104 ~ core::future::future::Future)), bound_vars: [] }, depth=2) should have been handled by fulfillment already.


thread 'rustc' (8091150) panicked at compiler/rustc_trait_selection/src/traits/select/mod.rs:775:21:
Box<dyn Any>
stack backtrace:
   0:        0x108a487b4 - <<std::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core::fmt::Display>::fmt
   1:        0x105d13e94 - core::fmt::write
   2:        0x108a5f520 - <std::sys::stdio::unix::Stderr as std::io::Write>::write_fmt
   3:        0x108a1d13c - std::panicking::default_hook::{closure#0}
   4:        0x108a39c58 - std::panicking::default_hook
   5:        0x106904f1c - std::panicking::update_hook::<alloc::boxed::Box<rustc_driver_impl::install_ice_hook::{closure#1}>>::{closure#0}
   6:        0x108a3a224 - std::panicking::panic_with_hook
   7:        0x106971bfc - std::panicking::begin_panic::<rustc_errors::ExplicitBug>::{closure#0}
   8:        0x10696495c - std::sys::backtrace::__rust_end_short_backtrace::<std::panicking::begin_panic<rustc_errors::ExplicitBug>::{closure#0}, !>
   9:        0x108b77274 - std::panicking::begin_panic::<rustc_errors::ExplicitBug>
  10:        0x108b77f58 - <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
  11:        0x108be2520 - rustc_middle::util::bug::opt_span_bug_fmt::<rustc_span::span_encoding::Span>::{closure#0}
  12:        0x107517374 - rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
  13:        0x1074d5884 - rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
  14:        0x108be6f88 - rustc_middle::util::bug::bug_fmt
  15:        0x10867e020 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively::{closure#0}::{closure#0}
  16:        0x108746e94 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively
  17:        0x1085795e4 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicates_recursively::<thin_vec::ThinVec<rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>>>
  18:        0x10867df80 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively::{closure#0}::{closure#0}
  19:        0x108746e94 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively
  20:        0x1085795e4 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicates_recursively::<thin_vec::ThinVec<rustc_infer::traits::Obligation<rustc_middle::ty::predicate::Predicate>>>
  21:        0x10867de58 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively::{closure#0}::{closure#0}
  22:        0x108746e94 - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_predicate_recursively
  23:        0x1086734d4 - <rustc_trait_selection::traits::select::SelectionContext>::evaluation_probe::<<rustc_trait_selection::traits::select::SelectionContext>::evaluate_root_obligation::{closure#0}>::{closure#0}
  24:        0x10874432c - <rustc_trait_selection::traits::select::SelectionContext>::evaluate_root_obligation
  25:        0x1088a644c - rustc_traits::evaluate_obligation::evaluate_obligation
  26:        0x108016738 - rustc_query_impl::query_impl::evaluate_obligation::invoke_provider_fn::__rust_begin_short_backtrace
  27:        0x107e94170 - rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::DefaultCache<rustc_type_ir::canonical::CanonicalQueryInput<rustc_middle::ty::context::TyCtxt, rustc_middle::ty::ParamEnvAnd<rustc_middle::ty::predicate::Predicate>>, rustc_middle::query::erase::ErasedData<[u8; 2usize]>>, false>
  28:        0x108016808 - rustc_query_impl::query_impl::evaluate_obligation::execute_query_non_incr::__rust_end_short_backtrace
  29:        0x1087c50f0 - <rustc_infer::infer::InferCtxt as rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation
  30:        0x1087c54ac - <rustc_infer::infer::InferCtxt as rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation_no_overflow
  31:        0x10873154c - <rustc_trait_selection::traits::fulfill::FulfillProcessor>::process_projection_obligation
  32:        0x1087e2480 - <rustc_trait_selection::traits::fulfill::FulfillProcessor as rustc_data_structures::obligation_forest::ObligationProcessor>::process_obligation
  33:        0x1085501e8 - <rustc_data_structures::obligation_forest::ObligationForest<rustc_trait_selection::traits::fulfill::PendingPredicateObligation>>::process_obligations::<rustc_trait_selection::traits::fulfill::FulfillProcessor>
  34:        0x106fbd0d8 - <rustc_trait_selection::traits::fulfill::FulfillmentContext<rustc_trait_selection::traits::FulfillmentError> as rustc_infer::traits::engine::TraitEngine<rustc_trait_selection::traits::FulfillmentError>>::try_evaluate_obligations
  35:        0x106ed6074 - <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_return_or_body_tail
  36:        0x106f9e008 - rustc_hir_typeck::check::check_fn
  37:        0x106e81684 - rustc_hir_typeck::typeck_with_inspect::{closure#0}
  38:        0x106ea8448 - rustc_hir_typeck::typeck_root
  39:        0x107e376a8 - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  40:        0x107ffe32c - rustc_query_impl::query_impl::typeck_root::execute_query_non_incr::__rust_end_short_backtrace
  41:        0x10768a364 - <rustc_middle::ty::context::TyCtxt>::typeck::<rustc_span::def_id::LocalDefId>
  42:        0x10772f410 - rustc_mir_build::thir::pattern::check_match::check_match
  43:        0x107ffc5a0 - rustc_query_impl::query_impl::check_match::invoke_provider_fn::__rust_begin_short_backtrace
  44:        0x107e2f8cc - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 1usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  45:        0x107ffc674 - rustc_query_impl::query_impl::check_match::execute_query_non_incr::__rust_end_short_backtrace
  46:        0x10772050c - rustc_mir_build::builder::build_mir_inner_impl
  47:        0x1078af7f0 - rustc_mir_transform::mir_built
  48:        0x107e376a8 - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  49:        0x108035aa4 - rustc_query_impl::query_impl::mir_built::execute_query_non_incr::__rust_end_short_backtrace
  50:        0x1078f7174 - rustc_mir_transform::ffi_unwind_calls::has_ffi_unwind_calls
  51:        0x10801900c - rustc_query_impl::query_impl::has_ffi_unwind_calls::invoke_provider_fn::__rust_begin_short_backtrace
  52:        0x107e2f8cc - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 1usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  53:        0x1080190dc - rustc_query_impl::query_impl::has_ffi_unwind_calls::execute_query_non_incr::__rust_end_short_backtrace
  54:        0x1078aafc8 - rustc_mir_transform::mir_promoted
  55:        0x1080007c4 - rustc_query_impl::query_impl::mir_promoted::invoke_provider_fn::__rust_begin_short_backtrace
  56:        0x107e2bae0 - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 16usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  57:        0x1080008a4 - rustc_query_impl::query_impl::mir_promoted::execute_query_non_incr::__rust_end_short_backtrace
  58:        0x1062b7014 - rustc_borrowck::mir_borrowck
  59:        0x107e376a8 - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  60:        0x1080002d8 - rustc_query_impl::query_impl::mir_borrowck::execute_query_non_incr::__rust_end_short_backtrace
  61:        0x106cd1fc8 - rustc_hir_analysis::collect::type_of::opaque::find_opaque_ty_constraints_for_rpit
  62:        0x106cb0d48 - rustc_hir_analysis::collect::type_of::type_of_opaque
  63:        0x107e57578 - rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::DefIdCache<rustc_middle::query::erase::ErasedData<[u8; 8usize]>>, false>
  64:        0x10800714c - rustc_query_impl::query_impl::type_of_opaque::execute_query_non_incr::__rust_end_short_backtrace
  65:        0x106cb34a8 - rustc_hir_analysis::collect::type_of::type_of
  66:        0x108033708 - rustc_query_impl::query_impl::type_of::invoke_provider_fn::__rust_begin_short_backtrace
  67:        0x107e57578 - rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::DefIdCache<rustc_middle::query::erase::ErasedData<[u8; 8usize]>>, false>
  68:        0x1080337ec - rustc_query_impl::query_impl::type_of::execute_query_non_incr::__rust_end_short_backtrace
  69:        0x106c67fb8 - rustc_hir_analysis::check::check::check_opaque
  70:        0x106c765e0 - rustc_hir_analysis::check::check::check_item_type
  71:        0x106c9683c - rustc_hir_analysis::check::wfcheck::check_well_formed
  72:        0x10800ef60 - rustc_query_impl::query_impl::check_well_formed::invoke_provider_fn::__rust_begin_short_backtrace
  73:        0x107e2f8cc - rustc_query_impl::execution::try_execute_query::<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 1usize]>, rustc_middle::dep_graph::graph::DepNodeIndex>, false>
  74:        0x10800f030 - rustc_query_impl::query_impl::check_well_formed::execute_query_non_incr::__rust_end_short_backtrace
  75:        0x106c89e10 - rustc_hir_analysis::check::wfcheck::check_type_wf
  76:        0x108001388 - rustc_query_impl::query_impl::check_type_wf::invoke_provider_fn::__rust_begin_short_backtrace
  77:        0x107e60914 - rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 1usize]>>, false>
  78:        0x108001450 - rustc_query_impl::query_impl::check_type_wf::execute_query_non_incr::__rust_end_short_backtrace
  79:        0x106bdf550 - rustc_hir_analysis::check_crate
  80:        0x1071b5d30 - rustc_interface::passes::analysis
  81:        0x107e5b370 - rustc_query_impl::execution::try_execute_query::<rustc_middle::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0usize]>>, false>
  82:        0x108033a60 - rustc_query_impl::query_impl::analysis::execute_query_non_incr::__rust_end_short_backtrace
  83:        0x1068f76a8 - rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>
  84:        0x10690833c - rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
  85:        0x1068fcc74 - 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}, ()>
  86:        0x10690ad20 - <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}
  87:        0x108a45384 - <std::sys::thread::unix::Thread>::new::thread_start
  88:        0x187389c58 - __pthread_cond_wait






query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `<Concrete as Service>::Future == make::{opaque#0}::{opaque#0}`
#1 [typeck_root] type-checking `make`
#2 [check_match] match-checking `make`
#3 [mir_built] building MIR for `make`
#4 [has_ffi_unwind_calls] checking if `make` contains FFI-unwind calls
#5 [mir_promoted] promoting constants in MIR for `make`
#6 [mir_borrowck] borrow-checking `make`
#7 [type_of_opaque] computing type of opaque `make::{opaque#0}`
#8 [type_of] computing type of `make::{opaque#0}`
#9 [check_well_formed] checking that `make::{opaque#0}` is well-formed
#10 [check_type_wf] checking that types are well-formed
#11 [analysis] running analysis passes on crate `min`
end of query stack
error: aborting due to 1 previous error

Regression

This is a regression from stable to nightly. PR #158477 ("Remove redundant dyn-compatibility check", merged 2026-06-29) introduced the panic: it replaced the DynCompatible arm in select/mod.rs with an unconditional bug! that assumes fulfillment always handles such obligations. That assumption does not hold on the evaluate_obligation query path, which calls SelectionContext directly. While type-checking the return type of make, the compiler evaluates the projection obligation <Concrete as Service>::Future == {opaque} through evaluate_obligation, which emits a DynCompatible(dyn Future) goal into SelectionContext::evaluate_predicate_recursively, where the new bug! fires.

  • last good: stable 1.91.0, nightly-2026-06-29
  • first bad: nightly-2026-06-30 (f46ec5218); also reproduces on 096694416

Anything else?

-Znext-solver compiles the code cleanly, because the next solver evaluates the dyn-compatibility goal through its own path instead of that arm. This looks fixable by next-solver.

The trigger is general. Replacing the boxed dyn Future with an Error = Box<dyn Error> associated type produces the same ICE on core::error::Error. Any return-position impl Trait whose associated-type bound resolves against a hidden type carrying a dyn object reaches it, which is a routine shape in tower and tokio code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-dyn-compatibilityArea: Dyn compatibility (formerly: object safety)A-dyn-traitArea: trait objects, vtable layoutA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions