{"id":"2ab0b932e68d5bff","repo":"rust-lang/rust","slug":"attribute-is-missing-tokens-self","errorCode":null,"errorMessage":"attribute is missing tokens: {self:?}","messagePattern":"attribute is missing tokens: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_ast/src/attr/mod.rs","lineNumber":299,"sourceCode":"            AttrKind::Normal(normal) => normal.item.meta(self.span),\n            AttrKind::Synthetic(..) | AttrKind::DocComment(..) => None,\n        }\n    }\n\n    pub fn meta_kind(&self) -> Option<MetaItemKind> {\n        match &self.kind {\n            AttrKind::Normal(normal) => normal.item.meta_kind(),\n            AttrKind::Synthetic(..) => unreachable!(),\n            AttrKind::DocComment(..) => None,\n        }\n    }\n\n    pub fn token_trees(&self) -> Vec<TokenTree> {\n        match self.kind {\n            AttrKind::Normal(ref normal) => normal\n                .tokens\n                .as_ref()\n                .unwrap_or_else(|| panic!(\"attribute is missing tokens: {self:?}\"))\n                .to_attr_token_stream()\n                .to_token_trees(),\n            // Empty tokens here ensures synthetic attributes are invisible to proc macros.\n            AttrKind::Synthetic(..) => vec![],\n            AttrKind::DocComment(comment_kind, data) => vec![TokenTree::token_alone(\n                token::DocComment(comment_kind, self.style, data),\n                self.span,\n            )],\n        }\n    }\n\n    pub fn deprecation_note(&self) -> Option<Ident> {\n        match &self.kind {\n            AttrKind::Normal(normal) if normal.item.path == sym::deprecated => {\n                let meta = &normal.item;\n\n                // #[deprecated = \"...\"]\n                if let Some(s) = meta.value_str() {","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_ast/src/attr/mod.rs#L281-L317","documentation":"`panic!(\"attribute is missing tokens: {self:?}\")` is fired by `Attribute::token_trees()` when an `AttrKind::Normal` attribute has `normal.tokens == None`. The invariant is that a fully-parsed Normal attribute always carries a lazy token stream; a missing stream means the attribute was constructed incompletely (tokens were never populated during parsing or were dropped by a transformation).","triggerScenarios":"Calling `attr.token_trees()` (or any path that reads `.tokens` on a `Normal` attribute) on an `Attribute` whose `NormalAttr.tokens` field is `None`. Happens when AST is hand-built or mutated (e.g., by a macro or a tool that constructs `Attribute` structs directly) without setting the `tokens` field.","commonSituations":"Procedural macros or rustc internals that build `Attribute` values via constructors that don't seed `tokens`. Refactors that move attribute creation and forget the token stream. Inconsistent deserialization paths that drop the tokens field. Rare in user code; common in tooling that synthesizes attributes.","solutions":["When constructing a `Normal` attribute, always populate `tokens` (e.g., via `AttrAnnotatedTokenStream` / `dummy_attr_tokens` helpers).","If you mutate attributes, propagate the original token stream rather than discarding it.","Reproduce with `RUST_BACKTRACE=1` to find which constructor left `tokens` as `None`, then fix that construction site."],"exampleFix":"// before\nAttribute { kind: AttrKind::Normal(NormalAttr { item, tokens: None }), .. }\n\n// after\nAttribute {\n    kind: AttrKind::Normal(NormalAttr {\n        item,\n        tokens: Some(LazyAttrTokenStream::new(...)),\n    }),\n    ..\n}","handlingStrategy":"validation","validationCode":"if let AttrKind::Normal(ref normal) = attr.kind {\n    if normal.tokens.is_none() {\n        // tokens not yet attached; do not call attr.token_trees()\n    }\n}","typeGuard":"fn attr_has_tokens(attr: &Attribute) -> bool {\n    match attr.kind {\n        AttrKind::Normal(ref n) => n.tokens.is_some(),\n        AttrKind::Synthetic(_) | AttrKind::DocComment(..) => true,\n    }\n}","tryCatchPattern":null,"preventionTips":["Synthetic and doc-comment attributes always have tokens; only normal attributes may miss them.","If you built the `Attribute` yourself, always attach `tokens` before passing it downstream.","Do not call `attr.token_trees()` on an attribute whose provenance you do not control."],"tags":["rustc","internals","ast","attributes","invariant"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}