gleam-lang/gleam · error

wrong index for inferred variant

Error message

wrong index for inferred variant

What it means

A panic raised when the exhaustiveness compiler builds checks for a `BranchMode::NamedType` branch whose `inferred_variant` index points past the list of that type's constructors. The index stored as the inferred variant must always index into the constructors vec; if it does not, the type-inference and exhaustiveness passes disagree.

Solutions

  1. Verify `inferred_variant` is computed against the same type whose `constructors` vec is in this BranchMode; recompute the index after any type substitution.
  2. Clear the stale `inferred_variant` (use `None`) when the type is re-inferred so the all-constructors path is taken instead.
  3. Reorder/lookup constructors by name instead of a captured positional index if constructor order can change.

Example fix

// before
let constructor = constructors.get(*index).expect("wrong index for inferred variant");
// after
let constructor = constructors.get(*index).unwrap_or_else(|| {
    panic!("inferred variant {} out of range for {} constructors", index, constructors.len())
});
Defensive patterns

Strategy: validation

Validate before calling

if let Some(index) = inferred_variant {
    assert!(index < constructors.len(), "inferred variant {} out of range", index);
}

Type guard

fn valid_inferred_variant(index: Option<usize>, constructors: &[Constructor]) -> Option<usize> {
    index.filter(|i| *i < constructors.len())
}

Try / catch

std::panic::catch_unwind(|| compile_branch(branch)).map_err(|_| Bug::WrongIndexForInferredVariant)

Prevention

When it happens

Trigger: Compiling a case subject whose inferred variant index was recorded by type inference, but the constructor list was rebuilt/reordered (e.g. after inference changed the variant, or the type was a different NamedType than the one the index was computed for).

Common situations: Gleam compiler contributors encounter this after changes to variant inference, custom-type ordering, or when `inferred_variant` is carried over between two different subject types (e.g. after unification substituted the type).

Related errors


AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14). Data as JSON: /api/errors/1f45c1387075df1f. Report an issue: GitHub.

Appendix: source

Thrown at compiler-core/src/exhaustiveness.rs:2533

            // decision tree node is only ever going to have two different paths:
            // one to follow if the list is empty, and one to follow if it's not.
            BranchMode::List { inner_type } => {
                vec![
                    RuntimeCheck::EmptyList,
                    self.is_list_check(inner_type.clone()),
                ]
            }

            // If we know that a specific variant is inferred we will require just
            // that one and not all the other ones we know for sure are not going to
            // be there.
            BranchMode::NamedType {
                constructors,
                inferred_variant: Some(index),
            } => {
                let constructor = constructors
                    .get(*index)
                    .expect("wrong index for inferred variant");
                vec![self.is_variant_check(*index, constructor)]
            }

            // Otherwise we know we'll need a check for each of its possible variants.
            BranchMode::NamedType { constructors, .. } => constructors
                .iter()
                .enumerate()
                .map(|(index, constructor)| self.is_variant_check(index, constructor))
                .collect_vec(),
        };

        // We then split all the branches using these checks and compile the
        // choices they've been split up into.
        let mut splitter = BranchSplitter::from_checks(known_checks);
        self.split_branches(&mut splitter, branches, pivot_var.clone(), &branch_mode);
        if branch_mode.is_infinite() {
            // If the branching is infinite, that means we always need to also have
            // a fallback (imagine you're pattern matching on an `Int` and put no

View on GitHub (pinned to 49f8762da5)