{"record":{"id":"c24aecfacdf0caaf","repo":"gleam-lang/gleam","slug":"no-unconditional-patterns-left","errorCode":null,"errorMessage":"no unconditional patterns left","messagePattern":"no unconditional patterns left","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/exhaustiveness.rs","lineNumber":3122,"sourceCode":"        pattern_check: PatternCheck,\n        mut branch: Branch,\n        branch_mode: &BranchMode,\n        compiler: &mut Compiler<'_>,\n    ) {\n        let pattern = compiler.pattern(pattern_check.pattern).clone();\n\n        // Bit array patterns are split in a different way that requires special\n        // handling. Instead of reasoning on overlapping checks what we do it we\n        // always split the decision tree in two distinct paths based on one of\n        // the bit array pattern's tests.\n        if let Pattern::BitArray { tests } = pattern {\n            self.add_checked_bit_array_branch(pattern_check, tests, branch, compiler);\n            return;\n        }\n\n        let kind = pattern\n            .to_runtime_check_kind()\n            .expect(\"no unconditional patterns left\");\n\n        let CheckOverlaps {\n            overlapping,\n            needs_new_choice,\n        } = self.check_overlaps(&kind);\n\n        // The branch is relevant to every existing choice its check overlaps\n        // with, so we add it (together with any newly discovered checks) to all\n        // of those paths. For a string prefix this also includes any longer\n        // prefixes and exact literals that start with it. When one of those\n        // matched but its branch then failed, control falls through to this\n        // shorter prefix.\n        for index in overlapping.iter() {\n            let (overlapping_check, branches) = self\n                .choices\n                .get_mut(*index)\n                .expect(\"check to already be a choice\");\n","sourceCodeStart":3104,"sourceCodeEnd":3140,"githubUrl":"https://github.com/gleam-lang/gleam/blob/49f8762da595eb3c8f576656a4200a142ca188c9/compiler-core/src/exhaustiveness.rs#L3104-L3140","documentation":"Panic from `pattern.to_runtime_check_kind().expect(\"no unconditional patterns left\")`. `to_runtime_check_kind` returns None for patterns that still contain unprocessed sub-checks (e.g. guards or nested patterns that cannot be a single unconditional check); this code assumed every pattern reaching it had been fully reduced to one runtime check kind.","triggerScenarios":"Compiling a case branch whose pattern is not yet a simple unconditional pattern — e.g. a pattern with a guard, or a nested/compound pattern that the earlier reduction step failed to split — reaching `compile_pattern`/`add_branch` and calling `to_runtime_check_kind`.","commonSituations":"Compiler developers hit this when adding new pattern forms (e.g. new literal or bit-array segment types) without teaching `to_runtime_check_kind` (or the reduction pass) about them.","solutions":["Extend `to_runtime_check_kind` to handle the new pattern shape, or ensure the pattern is fully simplified before reaching this code.","Check the caller's fast paths (bit-array/list handling above this line) cover every compound pattern kind.","Add a test with the pattern that panics and fix the reduction pass so it never forwards unsimplified patterns."],"exampleFix":"// before\nlet kind = pattern.to_runtime_check_kind().expect(\"no unconditional patterns left\");\n// after\nlet kind = pattern.to_runtime_check_kind().unwrap_or_else(|| {\n    panic!(\"pattern {:?} did not reduce to a runtime check kind\", pattern)\n});","handlingStrategy":"validation","validationCode":"// Only call when the pattern is a simple unconditional pattern:\nif pattern.to_runtime_check_kind().is_none() { simplify_pattern(pattern)?; }","typeGuard":"fn is_unconditional(pattern: &Pattern) -> bool {\n    pattern.to_runtime_check_kind().is_some()\n}","tryCatchPattern":"std::panic::catch_unwind(|| compile_pattern(p)).unwrap_or_else(|_| Err(Error::UnsupportedPattern(p.clone())))","preventionTips":["Extend to_runtime_check_kind whenever a new pattern kind is added.","Run the reduction pass exhaustively before compiling patterns.","Add a compile-fail/unit test for each new pattern shape."],"tags":["rust","compiler","panics","exhaustiveness","patterns"],"backgroundTag":"internal-invariant-violation","analyzedSha":"49f8762da595eb3c8f576656a4200a142ca188c9","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}