{"record":{"id":"85469f50f6419ad7","repo":"astral-sh/ruff","slug":"there-must-be-a-first-type-if-there-are-conflictin","errorCode":null,"errorMessage":"there must be a first type if there are conflicting types","messagePattern":"there must be a first type if there are conflicting types","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_python_semantic/src/place.rs","lineNumber":1990,"sourceCode":"                }\n            } else {\n                self.first_type = Some(element_ty);\n            }\n        }\n\n        self.qualifiers = self.qualifiers.union(element.qualifiers());\n    }\n\n    fn build(mut self) -> DeclaredTypeAndConflictingTypes<'db> {\n        let type_and_quals =\n            TypeAndQualifiers::new(self.inner.build(), TypeOrigin::Declared, self.qualifiers);\n        if self.conflicting_types.is_empty() {\n            (type_and_quals, None)\n        } else {\n            self.conflicting_types.insert_before(\n                0,\n                self.first_type\n                    .expect(\"there must be a first type if there are conflicting types\"),\n            );\n            (\n                type_and_quals,\n                Some(self.conflicting_types.into_boxed_slice()),\n            )\n        }\n    }\n}\n\n/// Implementation of [`place_from_declarations`].\n///\n/// ## Implementation Note\n/// This function gets called cross-module. It, therefore, shouldn't\n/// access any AST nodes from the file containing the declarations.\nfn place_from_declarations_impl<'db>(\n    db: &'db dyn Db,\n    env: &ProgramEnvironment<'db>,\n    declarations_iterator: DeclarationsIterator<'_, 'db>,","sourceCodeStart":1972,"sourceCodeEnd":2008,"githubUrl":"https://github.com/astral-sh/ruff/blob/fca5c7cf2cd2f8338f18b9485f936b8e9f07bd0b/crates/ty_python_semantic/src/place.rs#L1972-L2008","documentation":"DeclaredTypeAndConflictingTypesBuilder assembles a symbol's declared type plus the list of conflicting declared types recorded across multiple declarations. Its invariant is that whenever a conflicting type is recorded, the original first declared type is stashed in first_type; build() panics if conflicting_types is non-empty while first_type was never set.","triggerScenarios":"A symbol that receives two or more different declared types (for example `x: int` in one branch and `x: str]` in another, or repeated annotations) where the code path that pushed the conflicting type never recorded the first type first - a builder misuse or a missed update when a new conflict-recording path was added.","commonSituations":"Modules with multiple differently-annotated declarations of the same name (conditional imports, branch-local annotations); contributor changes to place_from_declarations conflict collection.","solutions":["Minimize the module to the two conflicting annotations that trigger the panic and file a ty issue with it","As a contributor: ensure every path that pushes onto conflicting_types sets first_type beforehand (record the original type before treating later types as conflicts)","Workaround until fixed: unify or remove one of the conflicting declarations for that name"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| check_file(&db, file)));\nmatch result {\n    Ok(diags) => diags,\n    Err(payload) => { log::warn!(\"ty panicked while declaring {}: {:?}\", file, payload); vec![] }\n}","preventionTips":["Avoid mixing multiple different annotations for one name across branches in a single module while a triggering bug is unfixed","When touching conflict collection in place.rs, set first_type on every path that appends to conflicting_types","Add builder unit tests covering the one-conflict and many-conflicts sequences"],"tags":["rust","ty","places","declared-types","panic","builder-invariant"],"backgroundTag":"builder-state-invariant","analyzedSha":"fca5c7cf2cd2f8338f18b9485f936b8e9f07bd0b","analyzedAt":"2026-08-20T16:33:49.445Z","contentChangedAt":"2026-08-20T16:33:49.445Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}