{"record":{"id":"c5abbda6884fa2d5","repo":"rust-lang/rust-analyzer","slug":"usetreelists-are-always-nested-in-usetrees","errorCode":null,"errorMessage":"UseTreeLists are always nested in UseTrees","messagePattern":"UseTreeLists are always nested in UseTrees","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/syntax/src/ast/node_ext.rs","lineNumber":465,"sourceCode":"    pub fn parent_use_tree_list(&self) -> Option<ast::UseTreeList> {\n        self.syntax().parent().and_then(ast::UseTreeList::cast)\n    }\n\n    pub fn top_use_tree(&self) -> ast::UseTree {\n        let mut this = self.clone();\n        while let Some(use_tree_list) = this.parent_use_tree_list() {\n            this = use_tree_list.parent_use_tree();\n        }\n        this\n    }\n}\n\nimpl ast::UseTreeList {\n    pub fn parent_use_tree(&self) -> ast::UseTree {\n        self.syntax()\n            .parent()\n            .and_then(ast::UseTree::cast)\n            .expect(\"UseTreeLists are always nested in UseTrees\")\n    }\n\n    pub fn has_inner_comment(&self) -> bool {\n        self.syntax()\n            .children_with_tokens()\n            .filter_map(|it| it.into_token())\n            .find_map(ast::Comment::cast)\n            .is_some()\n    }\n\n    pub fn comma(&self) -> impl Iterator<Item = SyntaxToken> {\n        self.syntax()\n            .children_with_tokens()\n            .filter_map(|it| it.into_token().filter(|it| it.kind() == T![,]))\n    }\n\n    /// Remove the unnecessary braces in current `UseTreeList`\n    pub fn remove_unnecessary_braces(mut self, editor: &SyntaxEditor) {","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/syntax/src/ast/node_ext.rs#L447-L483","documentation":"ast::UseTreeList::parent_use_tree() asserts that a UseTreeList (the braces part of a use item) is always nested directly inside a UseTree node. It casts the parent and panics otherwise. Like the other node_ext assertions, a panic means the structural grammar invariant was violated by a synthetic/mutated tree.","triggerScenarios":"Calling parent_use_tree() (directly or via remove_unnecessary_braces) on a detached or synthetic UseTreeList whose syntax parent is not a UseTree, or after edits invalidated the node's position in the tree.","commonSituations":"IDE assists (remove unnecessary braces) operating on stale nodes after concurrent edits; tests constructing UseTreeList nodes without an enclosing UseTree; reparse corruption (report upstream).","solutions":["Fetch a fresh UseTreeList from the current tree right before calling parent_use_tree() in assists.","Only call on nodes obtained by parsing real use items, not hand-built fragments.","Use a defensive cast (syntax().parent().and_then(ast::UseTree::cast)) when handling synthetic nodes.","If it panics on ordinary source, minimize the input and file a rust-analyzer bug."],"exampleFix":"// before\nlet use_tree = use_tree_list.parent_use_tree();\n// after\nlet use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast);\nif let Some(use_tree) = use_tree { /* ... */ }","handlingStrategy":"type-guard","validationCode":"// Verify the UseTreeList is nested in a UseTree before calling parent_use_tree\nfn has_use_tree_parent(list: &ast::UseTreeList) -> bool {\n    list.syntax().parent().map_or(false, |p| ast::UseTree::can_cast(p.kind()))\n}","typeGuard":"fn safe_parent_use_tree(list: &ast::UseTreeList) -> Option<ast::UseTree> {\n    list.syntax().parent().and_then(ast::UseTree::cast)\n}","tryCatchPattern":"let use_tree = std::panic::catch_unwind(AssertUnwindSafe(|| list.parent_use_tree()))\n    .ok()\n    .or_else(|| list.syntax().parent().and_then(ast::UseTree::cast));","preventionTips":["Only call on UseTreeLists obtained from parsed use items.","In assists like remove_unnecessary_braces, re-resolve the node immediately before editing.","Re-check parentage after any concurrent tree mutation.","Prefer Option-returning casts over expect accessors in assist code."],"tags":["rust","syntax","ast","invariant"],"backgroundTag":"ast-invariant-panic","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}