rust-lang/rust · critical
BikeshedGuaranteedNoDrop is not const
Error message
BikeshedGuaranteedNoDrop is not const
What it means
Internal `unreachable!` in the next-gen trait solver's const-effect assembly for `BikeshedGuaranteedNoDrop` (`core::marker::BikeshedGuaranteedNoDrop`), the marker that guarantees a type's drop glue is a no-op. It is a compiler-implemented marker with no const variant, so the candidate stub `consider_builtin_bikeshed_guaranteed_no_drop_candidate` is never meant to execute. Hitting it ICEs rustc.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/effect_goals.rs:451
)
}),
)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
fn consider_builtin_transmute_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
unreachable!("TransmuteFrom is not const")
}
fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
unreachable!("BikeshedGuaranteedNoDrop is not const");
}
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>,View on GitHub (pinned to 22057b88b0)
Solutions
- Remove the const/`~const` bound on `BikeshedGuaranteedNoDrop`; the marker has no const impl.
- Audit `#[const_trait]` traits for implicit marker supertraits that synthesize the bound.
- File an ICE upstream with a minimal reproducer and the `-Znext-solver` flag.
- Bisect nightlies to find the routing change that exposed the branch.
Example fix
// before
const fn hold<T: const BikeshedGuaranteedNoDrop>(_: T) {}
// after
fn hold<T: BikeshedGuaranteedNoDrop>(_: T) {} Defensive patterns
Strategy: validation
Validate before calling
// build.rs: reject const BikeshedGuaranteedNoDrop effect goals
fn main() {
let src = std::fs::read_to_string("src/lib.rs").unwrap_or_default();
for banned in ["~const BikeshedGuaranteedNoDrop", "const BikeshedGuaranteedNoDrop", "GuaranteedNoDrop"] {
assert!(!src.contains(banned), "rejected: {banned} — no const builtin candidate");
}
println!("cargo:rerun-if-changed=src/lib.rs");
} Prevention
- `BikeshedGuaranteedNoDrop` (the no-drop guarantee used by niche optimization / const destruct reasoning) has no const candidate (effect_goals.rs:451); do not write `T: const BikeshedGuaranteedNoDrop`.
- If you need a no-drop guarantee in const code, establish it manually: constrain the type to `Copy` or wrap in `core::mem::ManuallyDrop` and document the invariant.
- Avoid relying on the optimizer's drop-elision proof in const contexts; const drop reasoning only follows the `const Destruct` path.
- An ICE here with no explicit bound is a solver bug — report with a minimized const-eval reproducer.
When it happens
Trigger: The host-effect solver proves `T: const BikeshedGuaranteedNoDrop` / `~const BikeshedGuaranteedNoDrop`, e.g. by binding a const generic or `const fn` parameter to the marker, or by a `#[const_trait]` whose supertrait/implied bounds include `BikeshedGuaranteedNoDrop`.
Common situations: Nightly code combining `BikeshedGuaranteedNoDrop` with `const_trait_impl`; drop-analysis-driven generic const APIs; `-Znext-solver` on code that previously used the marker only at runtime; nightly regression after marker-trait effect routing changed.
Related errors
- DiscriminantKind is not const
- FusedIterator is not const
- AsyncIterator is not const
- Coroutine is not const
- TransmuteFrom is not const
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/68465d80414a9a6e.json.
Report an issue: GitHub.