rust-lang/rust · error
FIXME(comptime)
Error message
FIXME(comptime)
What it means
An `unimplemented!("FIXME(comptime)")` ICE in `rustc_trait_selection`'s effects (const-destruct) computation. When computing the const conditions for an ADT whose `Drop` impl is `Constness::Const { always: true }`, the effects code cannot yet express those conditions and panics at effects.rs:468. This is the effects-side counterpart of adt.rs:315.
Source
Thrown at compiler/rustc_trait_selection/src/traits/effects.rs:468
let tcx = selcx.tcx();
let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, obligation.cause.span);
let self_ty = obligation.predicate.self_ty();
let const_conditions = match *self_ty.kind() {
// `ManuallyDrop` is trivially `[const] Destruct` as we do not run any drop glue on it.
ty::Adt(adt_def, _) if adt_def.is_manually_drop() => thin_vec![],
// An ADT is `[const] Destruct` only if all of the fields are,
// *and* if there is a `Drop` impl, that `Drop` impl is also `[const]`.
ty::Adt(adt_def, args) => {
let mut const_conditions: ThinVec<_> = adt_def
.all_fields()
.map(|field| {
ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args).skip_norm_wip()])
})
.collect();
match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) {
Some(hir::Constness::Const { always: true }) => unimplemented!("FIXME(comptime)"),
// `Drop` impl exists, but it's not const. Type cannot be `[const] Destruct`.
Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
// `Drop` impl exists, and it's const. Require `Ty: [const] Drop` to hold.
Some(hir::Constness::Const { always: false }) => {
let drop_def_id = tcx.require_lang_item(LangItem::Drop, obligation.cause.span);
let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
const_conditions.push(drop_trait_ref);
}
// No `Drop` impl, no need to require anything else.
None => {}
}
const_conditions
}
ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
}
View on GitHub (pinned to 7088e4b63a)
Solutions
- Make the `Drop` impl non-const (or a normal const drop) so the `always: true` branch is avoided.
- Disable the experimental comptime/const-destruct feature gate.
- Track the upstream `FIXME(comptime)` work; upgrade when implemented.
Example fix
// before (always-const drop + const Destruct obligation -> ICE)
impl const Drop for T { ... }
const fn drop_in_const(x: T) { /* needs [const] Destruct */ }
// after — non-const drop, no const obligation
impl Drop for T { fn drop(&mut self) { ... } } Defensive patterns
Strategy: validation
Validate before calling
# Detect const Drop impls that may become always-const under comptime rg -nE 'impl\s+const\s+Drop|const\s+fn\s+drop' src/ # review for always-const
Prevention
- Do not require `[const] Destruct` for types with always-const Drop.
- Use non-const Drop in experimental comptime crates.
- Track upstream `FIXME(comptime)`.
When it happens
Trigger: A type has an always-const `Drop` impl, and the trait solver must evaluate whether the type implements `[const] Destruct` (i.e. const destruction is required, e.g. in a `const` context).
Common situations: Comptime / const-destruct experimentation on nightly producing `always: true` const destructors combined with a `[const] Destruct` obligation.
Related errors
- FIXME(comptime)
- FIXME(unsafe_binder)
- FIXME(unsafe_binder)
- Fn* are not yet const
- AsyncFn* are not yet const
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/2f3fb9db69130a05.
Report an issue: GitHub.