rust-lang/rust · error
Fn* are not yet const
Error message
Fn* are not yet const
What it means
`consider_builtin_fn_ptr_trait_candidate` (effect_goals.rs:292) is `unimplemented!` because built-in `Fn`/`FnMut`/`FnOnce` impls for raw fn pointers (`fn(..) -> ..`) are not yet supported under the const/host-effect system. Unlike the truly-unreachable cases, this is a deliberate 'not implemented yet' marker — the compiler knows fn pointers should eventually be const-callable but the candidate builder has not landed.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/effect_goals.rs:292
goal.with(
cx,
ty::ClauseKind::HostEffect(
goal.predicate.with_replaced_self_ty(cx, ty),
),
)
}),
)
})?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
fn consider_builtin_fn_ptr_trait_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
unimplemented!("Fn* are not yet const")
}
#[instrument(level = "trace", skip_all, ret)]
fn consider_builtin_fn_trait_candidates(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
_kind: rustc_type_ir::ClosureKind,
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
let cx = ecx.cx();
let self_ty = goal.predicate.self_ty();
let (inputs_and_output, def_id, args) =
structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output);
// A built-in `Fn` impl only holds if the output is sized.
// (FIXME: technically we only need to check this if the type is a fn ptr...)
let output_is_sized_pred =View on GitHub (pinned to 22057b88b0)
Solutions
- Avoid invoking the target through a fn pointer — call the `const fn` directly by name so the `FnDef` candidate (which IS handled, effect_goals.rs:296) is used instead of the fn-pointer path.
- Remove the `const`/`~const Fn` bound that is forcing the fn-pointer candidate.
- Upgrade nightly and track the const-fn-ptr implementation status; report the ICE if still present.
- Gate the affected module behind a non-const path until the feature stabilizes.
Example fix
// before: const call through a function pointer triggers the unimplemented path
const fn add(a: u32, b: u32) -> u32 { a + b }
const fn run(f: fn(u32, u32) -> u32) -> u32 { f(1, 2) } // ICE: fn ptr not yet const
// after: call the const fn directly so the FnDef candidate applies
const fn add(a: u32, b: u32) -> u32 { a + b }
const fn run() -> u32 { add(1, 2) } Defensive patterns
Strategy: validation
Validate before calling
// Fn*/FnMut*/FnOnce are explicitly non-const today. Reject closures passed to const eval.
const fn reject_fn_in_const<F: Fn()>(_f: &F) {} // will fail effect_goals if the next solver reaches it Type guard
// Narrow away from callable values before entering a const context.
fn is_closure_or_fn<T: ?Sized>() -> bool { false } // approximated; at the type level keep callables out of const generic params Prevention
- Never pass closures or function pointers into `const fn` or `const` generics; Fn* traits are not const-evaluable.
- Replace a const-time callable with a monomorphized `const fn` item referenced by name, not a closure.
- If you need a const callable, use a marker-type + `const fn` associated function pattern instead of `impl Fn`.
When it happens
Trigger: Reached when the next solver, evaluating a `T: const Fn(..)` (or `FnMut`/`FnOnce`) host-effect goal for a function-pointer self type, reaches the fn-pointer built-in candidate branch (effect_goals.rs:288).
Common situations: Calling a `const fn` through a function pointer inside another `const fn`/`const` context under `#![feature(const_for)]`/`host_effects`; storing a `const fn` in a `fn` typed value and then requiring it `~const Fn`.
Related errors
- AsyncFn* are not yet const
- Sized/MetaSized is never const
- AsyncFnKindHelper is not const
- Tuple trait is not const
- Pointee is not const
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/768caf97a28a075b.json.
Report an issue: GitHub.