{"record":{"id":"06703c39e16e58ee","repo":"astral-sh/ruff","slug":"accumulator-should-not-be-empty","errorCode":null,"errorMessage":"accumulator should not be empty","messagePattern":"accumulator should not be empty","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_python_semantic/src/types/constraints.rs","lineNumber":3002,"sourceCode":"    /// rather than by a union assembled from several alternatives. Exhausting the shared\n    /// traversal budget also returns false, leaving the original branch unchanged.\n    fn is_covered_by(\n        self,\n        storage: &ConstraintSetStorage<'_>,\n        other: Self,\n        remaining_visits: &mut usize,\n    ) -> bool {\n        if self == other || self == ALWAYS_FALSE || other == ALWAYS_TRUE {\n            return true;\n        }\n        let Some(remaining) = remaining_visits.checked_sub(1) else {\n            return false;\n        };\n        *remaining_visits = remaining;\n        let (Node::Interior(left), Node::Interior(right)) = (self.node(), other.node()) else {\n            return false;\n        };\n        let left = storage.interior_node_data(left.node());\n        let right = storage.interior_node_data(right.node());\n        match left.constraint.ordering().cmp(&right.constraint.ordering()) {\n            Ordering::Less => {\n                left.if_true.is_covered_by(storage, other, remaining_visits)\n                    && left\n                        .if_uncertain\n                        .is_covered_by(storage, other, remaining_visits)\n                    && left\n                        .if_false\n                        .is_covered_by(storage, other, remaining_visits)\n            }\n            Ordering::Equal => {\n                left.if_uncertain\n                    .is_covered_by(storage, other, remaining_visits)\n                    && (left\n                        .if_true\n                        .is_covered_by(storage, right.if_true, remaining_visits)\n                        || left.if_true.is_covered_by(","sourceCodeStart":2984,"sourceCodeEnd":3020,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ty_python_semantic/src/types/constraints.rs#L2984-L3020","documentation":"This routine combines nodes in a balanced tree using a SmallVec accumulator keyed by depth (the comment above it diagrams the a/0, ab/1, abcd/2 shape). The `pop().expect(...)` is guarded by `last().is_some_and(...)`, so it is logically unreachable: it exists to satisfy the Option returned by pop. Hitting it means the accumulator's depth invariants were broken elsewhere in the combining logic.","triggerScenarios":"A change to the depth bookkeeping - e.g. depth overflow of the u8 counter at 256+ combinations, combine returning early without popping, or mutations of the accumulator between the guard and the pop - makes the while-guard see an element pop cannot return.","commonSituations":"Editing the tree-combination code in constraints.rs (operator folding over many nodes); inference mdtests with hundreds of constraints after such edits.","solutions":["Check the depth type (u8) cannot wrap for realistic constraint counts, and that every path through the loop either pops or pushes consistently.","Replace the expect with a `debug_assert!` plus a `continue`-style recovery only after finding the actual invariant break; do not silence it blindly.","Minimize the failing constraint workload into a unit test in constraints.rs.","Report upstream with the reproducer if stock ty panics."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let combined = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    combine_all(db, env, nodes)\n}))\n.unwrap_or_else(|_| (one, None)); // degrade to the identity element","preventionTips":["A hit here means an algorithm bug, not bad input: report the constraint count and shape immediately.","Contributors: keep the accumulator depth invariant documented next to the diagram when editing this loop.","Chunk very large inference workloads while a fix is pending; depth is tracked in a u8."],"tags":["rust","panic","expect","ty","constraints","accumulator","algorithm","unreachable"],"backgroundTag":"constraint-solver-invariant-panic","analyzedSha":"15f3fe6b15a5f00172f34b0f542f8ea277f5a586","analyzedAt":"2026-08-20T16:33:49.445Z","contentChangedAt":"2026-08-20T16:33:49.445Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}