{"id":"0662efebdee5d35f","repo":"rust-lang/rust","slug":"attributes-not-supported-on-queries","errorCode":null,"errorMessage":"attributes not supported on queries","messagePattern":"attributes not supported on queries","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"compiler/rustc_macros/src/query.rs","lineNumber":21,"sourceCode":"use quote::{quote, quote_spanned};\nuse syn::parse::{Parse, ParseStream, Result};\nuse syn::punctuated::Punctuated;\nuse syn::spanned::Spanned;\nuse syn::{\n    AttrStyle, Attribute, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, parenthesized,\n    parse_macro_input, token,\n};\n\nmod kw {\n    syn::custom_keyword!(non_query);\n    syn::custom_keyword!(query);\n}\n\n/// Ensures only doc comment attributes are used\nfn check_attributes(attrs: Vec<Attribute>) -> Result<Vec<Attribute>> {\n    let inner = |attr: Attribute| {\n        if !attr.path().is_ident(\"doc\") {\n            Err(Error::new(attr.span(), \"attributes not supported on queries\"))\n        } else if attr.style != AttrStyle::Outer {\n            Err(Error::new(\n                attr.span(),\n                \"attributes must be outer attributes (`///`), not inner attributes\",\n            ))\n        } else {\n            Ok(attr)\n        }\n    };\n    attrs.into_iter().map(inner).collect()\n}\n\n/// Declaration of a compiler query.\n///\n/// ```ignore (illustrative)\n/// /// Doc comment for `my_query`.\n/// //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^              doc_comments\n/// query my_query(key: DefId) -> Value { anon }","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_macros/src/query.rs#L3-L39","documentation":"Reported by the check_attributes helper used by the query/non_query parsing macros in rustc_macros::query. While collecting attributes preceding a query declaration, any attribute whose path is not exactly doc is rejected, because only doc-comments are meaningful on query and non_query items in the rustc_query_system declaration files. Any other attribute (cfg, allow, derive, etc.) is treated as user error at macro expansion time.","triggerScenarios":"Inside the parse path for Query / NonQuery, input.call(Attribute::parse_outer) returns attributes; check_attributes maps each through inner; an attribute with attr.path() not ident \"doc\" returns syn::Error with this message. Triggered by writing e.g. #[allow(...)] or #[cfg(...)] above a `query foo(...) -> T { ... }` or `non_query Bar` declaration.","commonSituations":"Editing rustc_query_system or rustc query definition files (e.g. rustc_middle query definitions) and pasting a lint/cfg attribute that belongs on the surrounding module instead of the query; copy-paste from regular Rust items into a query definition file.","solutions":["Remove the non-doc attribute from above the query/non_query declaration","Move the attribute to the enclosing module/impl where it is actually intended","Keep only /// doc comments above query declarations; nothing else is permitted"],"exampleFix":"// before\n#[allow(unused)]\nquery my_query(key: DefId) -> Value { eval_always }\n// after\nquery my_query(key: DefId) -> Value { eval_always }","handlingStrategy":"validation","validationCode":"// 'attributes not supported on queries' — emitted by the rustc_macros query\n// macro when you attach attributes to a query definition. Validate at the AST\n// level before the macro expands:\nfn query_block_has_no_attrs(items: &[syn::Item]) -> Result<(), String> {\n    for item in items {\n        if let syn::Item::Macro(m) = item {\n            // inside a query! { ... } block the inner items must be bare fn decls\n            // with no outer attributes.\n            // (Simplified; real impl walks the macro token stream.)\n            let _ = &m.mac;\n        }\n    }\n    Ok(())\n}\n\n// Or simply: when editing compiler/query_system.rs, run a pre-commit check that\n// greps for #[...] lines inside rustc_queries! { } blocks.","typeGuard":"// Token-level guard used in CI to reject attribute tokens inside a queries! block.\nuse proc_macro2::TokenStream;\n\nfn queries_block_contains_attributes(tokens: &TokenStream) -> bool {\n    let mut iter = tokens.clone().into_iter().peekable();\n    while let Some(tt) = iter.next() {\n        if let proc_macro2::TokenTree::Punct(p) = &tt {\n            if p.as_char() == '#' {\n                return true; // any '# inside the queries! body is disallowed\n            }\n        }\n    }\n    false\n}","tryCatchPattern":"// Compile-time macro error; no runtime catch. Add a CI test:\n#[test]\nfn no_attributes_in_queries_block() {\n    let src = include_str!(\"../src/compiler/rustc_query_impl.rs\");\n    // crude: extract rustc_queries! { ... } spans and assert no '#' inside\n    let blocks = extract_queries_blocks(src);\n    for b in blocks {\n        assert!(!b.contains('#'), \"attributes not supported on queries; found: {}\", b);\n    }\n}","preventionTips":["When authoring rustc_queries! blocks, only declare query signatures — never annotate them with #[derive], #[cfg], etc.","If you need per-query configuration, use the macro's documented syntax (e.g. separators or named args), not attributes.","Run cargo expand on the queries macro during development to confirm what's accepted.","Add a CI grep test forbidding '#' inside rustc_queries! { ... } blocks.","Keep query definitions minimal and config-driven via the macro DSL, not via Rust attributes."],"tags":["proc-macro","rustc-internal","query-system","macro-parse"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}