gleam-lang/gleam · error

case with no subjects

Error message

case with no subjects

What it means

When a `case` expression being compiled has no branches, the compiler still needs at least one subject variable to split the decision tree on; `subject_variables.first().expect("case with no subjects")` panics if the expression has zero subjects. This signals a malformed (subject-less) case expression reached the exhaustiveness compiler.

Solutions

  1. Ensure every case expression reaching compilation has at least one subject; fix the producer of the malformed AST node
  2. If a subject-less case is legitimate, handle it before calling `split_and_compile_with_pivot_var` (e.g. return a catch-all decision)
  3. Trace with a backtrace which pass created the empty-subject case and add validation there
  4. End users: file a compiler bug with the triggering source code

Example fix

// before
let var = self.subject_variables.first().expect("case with no subjects").clone();
// after
let var = self.subject_variables.first().cloned().unwrap_or_else(|| panic!("compiling case with zero subjects; frontend should have rejected this"));
Defensive patterns

Strategy: validation

Validate before calling

if branches.is_empty() && subject_variables.is_empty() {
    return Err(Error::CaseExpressionMissingSubjects);
}

Type guard

fn compilable(case: &CaseToCompile) -> bool { !case.subject_variables.is_empty() }

Prevention

When it happens

Trigger: Compiling `CompileCaseResult`/case compilation where `branches` is empty AND the original case expression had no subjects (e.g. `case` with no arguments produced by a buggy earlier pass).

Common situations: Encountered when working on Gleam compiler internals: a desugaring or codegen pass constructing a case expression without subjects, or fuzz input where subject validation was skipped.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

    pub fn add_pattern(&mut self, pattern: &TypedPattern) {
        let pattern = self.register(pattern);
        let var = self
            .subject_variables
            .first()
            .expect("wrong number of subject variables for pattern");
        let branch = Branch::new(self.number_of_clauses, 0, vec![var.is(pattern)], false);
        self.number_of_clauses += 1;
        self.branches.push(branch);
    }

    pub fn compile(self, env: &Environment<'_>) -> CompileCaseResult {
        let mut compiler = Compiler::new(env, self.variable_id, self.patterns);

        let decision = if self.branches.is_empty() {
            let var = self
                .subject_variables
                .first()
                .expect("case with no subjects")
                .clone();

            compiler.split_and_compile_with_pivot_var(var, VecDeque::new())
        } else {
            compiler.compile(self.branches.into())
        };

        CompileCaseResult {
            diagnostics: compiler.diagnostics,
            compiled_case: CompiledCase {
                tree: decision,
                subject_variables: self.subject_variables,
            },
        }
    }

    /// Registers a typed pattern (and all its sub-patterns) into this
    /// `CaseToCompile`'s pattern arena, returning an id to get the pattern back.

View on GitHub (pinned to 49f8762da5)