{"record":{"id":"528be1d47d8cba09","repo":"rust-lang/rust-analyzer","slug":"enumvariants-are-always-nested-in-enums","errorCode":null,"errorMessage":"EnumVariants are always nested in Enums","messagePattern":"EnumVariants are always nested in Enums","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/syntax/src/ast/node_ext.rs","lineNumber":778,"sourceCode":"            Some(ast::Pat::BoxPat(pat)) => match pat.pat() {\n                Some(ast::Pat::IdentPat(pat)) => {\n                    let name = pat.name()?;\n                    Some(NameOrNameRef::Name(name))\n                }\n                _ => None,\n            },\n            _ => None,\n        }\n    }\n}\n\nimpl ast::Variant {\n    pub fn parent_enum(&self) -> ast::Enum {\n        self.syntax()\n            .parent()\n            .and_then(|it| it.parent())\n            .and_then(ast::Enum::cast)\n            .expect(\"EnumVariants are always nested in Enums\")\n    }\n    pub fn kind(&self) -> StructKind {\n        StructKind::from_node(self)\n    }\n}\n\nimpl ast::Item {\n    pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {\n        ast::AnyHasGenericParams::cast(self.syntax().clone())?.generic_param_list()\n    }\n}\n\nimpl ast::Type {\n    pub fn generic_arg_list(&self) -> Option<ast::GenericArgList> {\n        if let ast::Type::PathType(path_type) = self {\n            path_type.path()?.segment()?.generic_arg_list()\n        } else {\n            None","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/syntax/src/ast/node_ext.rs#L760-L796","documentation":"`ast::Variant::parent_enum()` unwraps two parent links from a variant node and casts the result to `ast::Enum`. The library asserts as an internal invariant that a `Variant` (a Rust enum variant) is always nested inside an `ENUM_VARIANTS` node inside an `Enum`, so if the cast fails the tree is corrupt or the node is not actually an enum variant. This is an `expect` on a structural invariant, not a recoverable API error.","triggerScenarios":"Calling `parent_enum()` on a `Variant` node that was detached from its tree (syntax().parent() is None), a Variant constructed outside a real `Enum` (e.g. a struct/tuple-struct field repurposed or a manually/incorrectly built tree), or on a node whose grandparent is not castable to `ast::Enum`.","commonSituations":"Transforming or cloning nodes across trees and keeping stale handles to detached nodes; hand-crafting syntax trees in tests or a syntax_editor rewrite; misusing the AST node_ext helpers on nodes obtained from non-enum contexts after refactors of the grammar.","solutions":["Ensure the `Variant` node is still attached to a real `ast::Enum` in a live tree before calling `parent_enum()`","Re-obtain the node from the current tree instead of using a cached handle from before a rewrite/mutation","Replace the expect with `and_then(ast::Enum::cast)` returning `Option<ast::Enum>` if the caller's tree may be non-standard","Verify the node kind is actually VARIANT (not a tuple/record field) before casting"],"exampleFix":"// before\nlet enum_node = variant.parent_enum();\n// after\nlet Some(enum_node) = ast::Enum::cast(variant.syntax().parent()?.parent()?) else { return None; };","handlingStrategy":"validation","validationCode":"fn is_attached_enum_variant(v: &ast::Variant) -> bool {\n    v.syntax().parent()\n        .and_then(|p| p.parent())\n        .and_then(ast::Enum::cast)\n        .is_some()\n}","typeGuard":"fn parent_enum(v: &ast::Variant) -> Option<ast::Enum> {\n    v.syntax().parent()?.parent().and_then(ast::Enum::cast)\n}","tryCatchPattern":null,"preventionTips":["Re-fetch nodes from the current tree after any mutation instead of caching handles","Check node.kind() is VARIANT before using Variant-specific helpers","Prefer Option-returning navigation (syntax().parent() chains) in your own code over expect-based helpers"],"tags":["rust","syntax-tree","invariant-assertion","panic"],"backgroundTag":"detached-syntax-node","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"}