rust-lang/rust · critical

Field is not const

Error message

Field is not const

What it means

Internal `unreachable!` in the next-gen trait solver's const-effect candidate assembly for the built-in `Field` trait (`core::marker::Field`, part of the unsafe field-access / `proj` machinery). `Field` has no const implementation, so `consider_builtin_field_candidate` is a never-executed stub; reaching it means the solver routed a `T: const Field<...>` goal into built-in candidate assembly and the compiler ICEs.

Source

Thrown at compiler/rustc_next_trait_solver/src/solve/effect_goals.rs:472

    fn consider_builtin_try_as_dyn_candidate(
        _ecx: &mut EvalCtxt<'_, D>,
        goal: Goal<I, Self>,
    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
        unreachable!("`TryAsDynCompat` is not const: {:?}", goal)
    }

    fn consider_structural_builtin_unsize_candidates(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<I, Self>,
    ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
        unreachable!("Unsize is not const")
    }

    fn consider_builtin_field_candidate(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<<D as SolverDelegate>::Interner, Self>,
    ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolutionOrRerunNonErased> {
        unreachable!("Field is not const")
    }
}

impl<D, I> EvalCtxt<'_, D>
where
    D: SolverDelegate<Interner = I>,
    I: Interner,
{
    #[instrument(level = "trace", skip(self))]
    pub(super) fn compute_host_effect_goal(
        &mut self,
        goal: Goal<I, ty::HostEffectPredicate<I>>,
    ) -> QueryResultOrRerunNonErased<I> {
        let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
            let trait_goal: Goal<I, ty::TraitPredicate<I>> =
                goal.with(ecx.cx(), goal.predicate.trait_ref);
            ecx.compute_trait_goal(trait_goal).map_err(Into::into)
        })?;

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Remove the const/`~const Field` bound — field projection is not const.
  2. Audit `#[const_trait]` traits for `Field` in their implied bounds.
  3. Report the ICE upstream with a minimal reproducer and the `-Znext-solver`/`proj` feature flags.
  4. Bisect nightlies; the Field trait and its const routing are highly unstable.

Example fix

// before
const fn get<S, F>(s: &S) -> &F::Type where S: const Field<F> { unimplemented!() }

// after
fn get<S, F>(s: &S) -> &F::Type where S: Field<F> { unimplemented!() }
Defensive patterns

Strategy: validation

Validate before calling

// build.rs: reject const Field (field-offset projection) bounds
fn main() {
    let src = std::fs::read_to_string("src/lib.rs").unwrap_or_default();
    for banned in ["~const Field", "const Field", "core::field::Field"] {
        assert!(!src.contains(banned), "rejected: {banned} — Field projection is not const");
    }
    println!("cargo:rerun-if-changed=src/lib.rs");
}

Prevention

When it happens

Trigger: A host-effect goal resolves to the `Field` lang item: `T: const Field<F>` / `~const Field<F>`, typically via nightly field-projection (`proj`) experiments inside `const fn`, or a `#[const_trait]` whose implied bounds include `Field`.

Common situations: Using nightly field-projection / `unsafe` field-access features together with `const_trait_impl`; `-Znext-solver` on struct-projection-heavy generic code; nightly regression as field-trait routing was wired into effect-goal assembly.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/851adc746352cd93.json. Report an issue: GitHub.