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

  1. Ensure the segment belongs to a parsed tree and is not detached before calling parent_path().
  2. After tree mutations, re-query the segment from the new tree instead of reusing stale syntax nodes.
  3. Use a defensive cast (syntax().parent().and_then(ast::Path::cast)) if you must handle synthetic nodes.
  4. 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

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


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/87895ae1422ef06a. Report an issue: GitHub.