Skip to content

ICE: could not replace AliasTerm on stable when a dyn Fn*-supertrait object's signature uses a const-length array #159457

Description

@MarijnS95

Note

Authors' note: this report was generated with Claude, that quickly reduced a 4-line repro from a massive many-crate repository. It is a regression to us in the 1.96 -> 1.97.0/.1 upgrade. It compiles fine under rustc +1.96.0 --crate-type lib ice.rs.

Code

Compiles with rustc --crate-type lib ice.rs (no flags needed — happens on the default solver on stable, because vtable-slot resolution invokes the next solver internally):

const N: usize = 6;
pub trait CustomPassFn: FnOnce(&[u32; N]) {}
impl<F: FnOnce(&[u32; N])> CustomPassFn for F {}
pub fn run(f: Box<dyn CustomPassFn>, b: &[u32; N]) { f(b) }

Bisecting the ingredients:

  • Required: the array length is a named const ([u32; N]). Replacing N with the literal 6 compiles fine.
  • Required: the boxed dyn CustomPassFn is actually called (f(b)), forcing vtable-slot resolution.

This looks like the same family as #155761 and #155035, but those use associated-type / nested-dyn triggers and require -Znext-solver explicitly. This variant reproduces on stable with the default solver and no flags, triggered by a const-length array in the Fn signature.

Meta

rustc --version --verbose:

rustc 1.97.1 (8bab26f4f 2026-07-14)
host: aarch64-apple-darwin

Also reproduces on editions 2015, 2021, and 2024.

Error output

thread 'rustc' panicked at compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs:1005:13:
could not replace AliasTerm { args: [dyn [.. Trait(CustomPassFn) .., Projection(ExistentialProjection {
def_id: ..core::ops::function::FnOnce::Output, args: [(&'^0 [u32; 6_usize])], term: Term::Ty(()), .. })] + '!0,
(&'?3 [u32; UnevaluatedConst { def: ..CustomPassFn::{constant#0}, args: [] }])], kind: ProjectionTy {
def_id: ..core::ops::function::FnOnce::Output }, .. } with term from ...
Backtrace
   2: <rustc_next_trait_solver::solve::assembly::structural_traits::ReplaceProjectionWith<..>>::try_eagerly_replace_alias
   5: rustc_next_trait_solver::solve::assembly::structural_traits::predicates_for_object_candidate::<..>
   6: <..TraitPredicate<..> as ..GoalKind<..>>::match_assumption::<..probe_and_consider_object_bound_candidate..>
   8: <..EvalCtxt<..>>::compute_trait_goal
  15: <..FulfillmentCtxt<..> as ..TraitEngine<..>>::try_evaluate_obligations
  16: rustc_trait_selection::traits::impossible_predicates
  17: rustc_trait_selection::traits::instantiate_and_check_impossible_predicates
  18: rustc_trait_selection::traits::vtable::first_method_vtable_slot
  20: rustc_ty_utils::instance::resolve_instance_raw
  23: <..MirUsedCollector as ..Visitor>::visit_terminator
  24: rustc_monomorphize::collector::items_of_instance

Query stack:

#0 [instantiate_and_check_impossible_predicates] checking impossible instantiated predicates: `CustomPassFn`
#1 [first_method_vtable_slot] finding the slot within the vtable of `dyn CustomPassFn<Output = ()>` for the implementation of `core::ops::function::FnOnce`

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-mediumMedium priorityS-has-bisectionStatus: A bisection has been found for this issueT-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions