rust-lang/rust-analyzer · error
UseTreeLists are always nested in UseTrees
Error message
UseTreeLists are always nested in UseTrees
What it means
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.
Source
Thrown at crates/syntax/src/ast/node_ext.rs:465
pub fn parent_use_tree_list(&self) -> Option<ast::UseTreeList> {
self.syntax().parent().and_then(ast::UseTreeList::cast)
}
pub fn top_use_tree(&self) -> ast::UseTree {
let mut this = self.clone();
while let Some(use_tree_list) = this.parent_use_tree_list() {
this = use_tree_list.parent_use_tree();
}
this
}
}
impl ast::UseTreeList {
pub fn parent_use_tree(&self) -> ast::UseTree {
self.syntax()
.parent()
.and_then(ast::UseTree::cast)
.expect("UseTreeLists are always nested in UseTrees")
}
pub fn has_inner_comment(&self) -> bool {
self.syntax()
.children_with_tokens()
.filter_map(|it| it.into_token())
.find_map(ast::Comment::cast)
.is_some()
}
pub fn comma(&self) -> impl Iterator<Item = SyntaxToken> {
self.syntax()
.children_with_tokens()
.filter_map(|it| it.into_token().filter(|it| it.kind() == T![,]))
}
/// Remove the unnecessary braces in current `UseTreeList`
pub fn remove_unnecessary_braces(mut self, editor: &SyntaxEditor) {View on GitHub (pinned to e8f7e90aa3)
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.
Example fix
// before
let use_tree = use_tree_list.parent_use_tree();
// after
let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast);
if let Some(use_tree) = use_tree { /* ... */ } Defensive patterns
Strategy: type-guard
Validate before calling
// Verify the UseTreeList is nested in a UseTree before calling parent_use_tree
fn has_use_tree_parent(list: &ast::UseTreeList) -> bool {
list.syntax().parent().map_or(false, |p| ast::UseTree::can_cast(p.kind()))
} Type guard
fn safe_parent_use_tree(list: &ast::UseTreeList) -> Option<ast::UseTree> {
list.syntax().parent().and_then(ast::UseTree::cast)
} Try / catch
let use_tree = std::panic::catch_unwind(AssertUnwindSafe(|| list.parent_use_tree()))
.ok()
.or_else(|| list.syntax().parent().and_then(ast::UseTree::cast)); Prevention
- 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.
When it happens
Trigger: 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.
Common situations: IDE assists (remove unnecessary braces) operating on stale nodes after concurrent edits; tests constructing UseTreeList nodes without an enclosing UseTree; reparse corruption (report upstream).
Related errors
- `ast::DocComment` must have a comment token
- segments are always nested in paths
- AstIdMap node mismatch with node `{ptr:?}`
- you have way too many items in the same file!
- Can't find SyntaxNodePtr {:?} in AstIdMap: {:?}
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/c5abbda6884fa2d5.
Report an issue: GitHub.