rust-lang/rust-analyzer · error
segments are always nested in paths
Error message
segments are always nested in paths
What it means
ast::PathSegment::parent_path() asserts that a path segment's parent in the syntax tree is always a Path node. It casts the parent and panics if the cast fails. The grammar guarantees PathSegment only appears inside Path, so a panic signals a hand-built or corrupted tree rather than user code error.
Source
Thrown at crates/syntax/src/ast/node_ext.rs:338
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathSegmentKind {
Name(ast::NameRef),
Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
SelfTypeKw,
SelfKw,
SuperKw,
CrateKw,
}
impl ast::PathSegment {
pub fn parent_path(&self) -> ast::Path {
self.syntax()
.parent()
.and_then(ast::Path::cast)
.expect("segments are always nested in paths")
}
pub fn crate_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.crate_token())
}
pub fn self_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.self_token())
}
pub fn self_type_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.Self_token())
}
pub fn super_token(&self) -> Option<SyntaxToken> {
self.name_ref().and_then(|it| it.super_token())
}
View on GitHub (pinned to e8f7e90aa3)
Solutions
- Ensure the segment belongs to a parsed tree and is not detached before calling parent_path().
- After tree mutations, re-query the segment from the new tree instead of reusing stale syntax nodes.
- Use a defensive cast (syntax().parent().and_then(ast::Path::cast)) if you must handle synthetic nodes.
- If reproducible on plain parsed source, minimize and file a rust-analyzer parser bug.
Example fix
// before
let path = segment.parent_path();
// after
let path = segment.syntax().parent().and_then(ast::Path::cast);
if let Some(path) = path { /* ... */ } Defensive patterns
Strategy: type-guard
Validate before calling
// Verify the segment is attached with a Path parent before calling parent_path
fn segment_has_path_parent(segment: &ast::PathSegment) -> bool {
segment.syntax().parent().map_or(false, |p| ast::Path::can_cast(p.kind()))
} Type guard
fn safe_parent_path(segment: &ast::PathSegment) -> Option<ast::Path> {
segment.syntax().parent().and_then(ast::Path::cast)
} Try / catch
let path = std::panic::catch_unwind(AssertUnwindSafe(|| segment.parent_path()))
.ok()
.or_else(|| segment.syntax().parent().and_then(ast::Path::cast)); Prevention
- Never call on detached/synthetic PathSegment nodes.
- Drop stale syntax node references after tree edits and re-query.
- In IDE assists, re-resolve nodes from the current file version.
- Use and_then(cast) chains instead of expect in downstream code.
When it happens
Trigger: Calling parent_path() on a PathSegment node detached from a tree (no parent), on a synthetic segment whose parent is not a Path, or after tree mutation reparented the segment. Called by top_path() and validate_path_keywords().
Common situations: Constructing synthetic AST nodes in tests or IDE assists without a Path parent; mutating the tree and keeping stale segment references; incremental-reparse corruption (report upstream).
Related errors
- `ast::DocComment` must have a comment token
- UseTreeLists are always nested in UseTrees
- 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/87895ae1422ef06a.
Report an issue: GitHub.