rust-lang/rust · error · syn::Error

attributes not supported on queries

Error message

attributes not supported on queries

What it means

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.

Source

Thrown at compiler/rustc_macros/src/query.rs:21

use quote::{quote, quote_spanned};
use syn::parse::{Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{
    AttrStyle, Attribute, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, parenthesized,
    parse_macro_input, token,
};

mod kw {
    syn::custom_keyword!(non_query);
    syn::custom_keyword!(query);
}

/// Ensures only doc comment attributes are used
fn check_attributes(attrs: Vec<Attribute>) -> Result<Vec<Attribute>> {
    let inner = |attr: Attribute| {
        if !attr.path().is_ident("doc") {
            Err(Error::new(attr.span(), "attributes not supported on queries"))
        } else if attr.style != AttrStyle::Outer {
            Err(Error::new(
                attr.span(),
                "attributes must be outer attributes (`///`), not inner attributes",
            ))
        } else {
            Ok(attr)
        }
    };
    attrs.into_iter().map(inner).collect()
}

/// Declaration of a compiler query.
///
/// ```ignore (illustrative)
/// /// Doc comment for `my_query`.
/// //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^              doc_comments
/// query my_query(key: DefId) -> Value { anon }

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Remove the non-doc attribute from above the query/non_query declaration
  2. Move the attribute to the enclosing module/impl where it is actually intended
  3. Keep only /// doc comments above query declarations; nothing else is permitted

Example fix

// before
#[allow(unused)]
query my_query(key: DefId) -> Value { eval_always }
// after
query my_query(key: DefId) -> Value { eval_always }
Defensive patterns

Strategy: validation

Validate before calling

// 'attributes not supported on queries' — emitted by the rustc_macros query
// macro when you attach attributes to a query definition. Validate at the AST
// level before the macro expands:
fn query_block_has_no_attrs(items: &[syn::Item]) -> Result<(), String> {
    for item in items {
        if let syn::Item::Macro(m) = item {
            // inside a query! { ... } block the inner items must be bare fn decls
            // with no outer attributes.
            // (Simplified; real impl walks the macro token stream.)
            let _ = &m.mac;
        }
    }
    Ok(())
}

// Or simply: when editing compiler/query_system.rs, run a pre-commit check that
// greps for #[...] lines inside rustc_queries! { } blocks.

Type guard

// Token-level guard used in CI to reject attribute tokens inside a queries! block.
use proc_macro2::TokenStream;

fn queries_block_contains_attributes(tokens: &TokenStream) -> bool {
    let mut iter = tokens.clone().into_iter().peekable();
    while let Some(tt) = iter.next() {
        if let proc_macro2::TokenTree::Punct(p) = &tt {
            if p.as_char() == '#' {
                return true; // any '# inside the queries! body is disallowed
            }
        }
    }
    false
}

Try / catch

// Compile-time macro error; no runtime catch. Add a CI test:
#[test]
fn no_attributes_in_queries_block() {
    let src = include_str!("../src/compiler/rustc_query_impl.rs");
    // crude: extract rustc_queries! { ... } spans and assert no '#' inside
    let blocks = extract_queries_blocks(src);
    for b in blocks {
        assert!(!b.contains('#'), "attributes not supported on queries; found: {}", b);
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/0662efebdee5d35f.json. Report an issue: GitHub.