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

  1. Make the `Drop` impl non-const (or a normal const drop) so the `always: true` branch is avoided.
  2. Disable the experimental comptime/const-destruct feature gate.
  3. 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

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


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/2f3fb9db69130a05. Report an issue: GitHub.