{"record":{"id":"71bf16573b4039e3","repo":"astral-sh/ruff","slug":"typevar-should-be-interned-before-ordering","errorCode":null,"errorMessage":"typevar should be interned before ordering","messagePattern":"typevar should be interned before ordering","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_python_semantic/src/types/constraints.rs","lineNumber":1398,"sourceCode":"                    support.insert(typevar);\n                }\n                walk_type_with_recursion_guard(db, ty, self, &self.recursion_guard);\n            }\n        }\n\n        InternMentionedTypevars {\n            env,\n            storage: RefCell::new(self),\n            support: RefCell::new(support),\n            recursion_guard: TypeCollector::default(),\n        }\n        .visit_type(db, ty);\n    }\n\n    /// Interns all of the typevars mentioned in a constraint in a stable order.\n    fn intern_constraint_typevars(\n        &mut self,\n        db: &'db dyn Db,\n        env: &ProgramEnvironment<'db>,\n        constraint: Constraint<'db>,\n    ) -> Support {\n        let mut support = Support::default();\n        support.insert(self.intern_typevar(db, constraint.typevar()));\n        for bound in constraint.iter_stored_bounds() {\n            self.intern_mentioned_typevars_in_type(db, env, bound.ty(), &mut support);\n        }\n        support\n    }\n\n    fn intern_constraint(\n        &mut self,\n        db: &'db dyn Db,\n        env: &ProgramEnvironment<'db>,\n        data: Constraint<'db>,\n    ) -> ConstraintId {\n        let support = self.intern_constraint_typevars(db, env, data);","sourceCodeStart":1380,"sourceCodeEnd":1416,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ty_python_semantic/src/types/constraints.rs#L1380-L1416","documentation":"Constraint-set storage interns every typevar through `intern_typevar` before it can be ordered; `typevar_id` only performs a lookup in `typevar_cache` keyed by typevar identity. The expect fires when ordering is requested for a `BoundTypeVarInstance` that was never interned in this builder - a typevar from another storage/overlay, or one added without going through the interning path.","triggerScenarios":"Calling ordering logic on a typevar whose constraints were never loaded into this builder: mixing storages, using a typevar after compaction split the storage, or a new code path that creates constraints without interning the typevar first.","commonSituations":"Contributions adding constraint-producing operations that bypass `intern_typevar`; overlay/borrow issues where the cache is ensured (`ensure_overlay_identity_caches`) but never populated; ordering-sensitive mdtests failing after a solver refactor.","solutions":["Ensure every code path that can later order a typevar calls `intern_typevar` (constraints.rs:1261) when adding its constraints.","If ordering foreign typevars is legitimate, make `typevar_id` intern on miss instead of expecting.","Add a regression test that orders a typevar immediately after adding constraints and one after compaction.","Report upstream with the reproducer if stock ty panics."],"exampleFix":"// before\nlet id = self.typevar_id(db, typevar);\n\n// after: intern first, ordering stays a pure lookup\nlet id = {\n    self.storage.borrow_mut().intern_typevar(db, typevar);\n    self.typevar_id(db, typevar)\n};","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let id = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    builder.typevar_id(db, typevar)\n}))\n.ok(); // callers must treat None as 'not yet known to this builder'","preventionTips":["Contributors: every constraint-adding path must intern the typevar first; ordering is lookup-only by design.","Never reuse typevars across builders/storages in tests.","Reduce repros to the smallest typevar set that still panics before reporting."],"tags":["rust","panic","expect","ty","constraints","typevar","interning","ordering"],"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"}