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

attributes must be outer attributes (`///`), not inner…

Error message

attributes must be outer attributes (`///`), not inner attributes

What it means

Emitted by check_attributes in the rustc_queries! macro when a #[doc] attribute uses inner-attribute syntax (//! or #[doc = ...] with AttrStyle::Inner) instead of outer-attribute syntax (/// or #[doc = ...] with AttrStyle::Outer). Only outer doc comments are allowed on individual query declarations. Inner doc comments (which document the enclosing item/module) don't make semantic sense on individual query entries.

Solutions

  1. Change the inner doc comment //! to an outer doc comment /// on the query line.
  2. If documenting the query group as a whole, place the //! comment outside the rustc_queries! invocation, not inside it on individual queries.

Example fix

// before
rustc_queries! {
    //! Computes the type of an expression.
    query type_of(key: DefId) -> Ty<'tcx> { desc { "type of `{}`", key } }
}
// after: use /// (outer) instead of //! (inner)
rustc_queries! {
    /// Computes the type of an expression.
    query type_of(key: DefId) -> Ty<'tcx> { desc { "type of `{}`", key } }
}
Defensive patterns

Strategy: validation

Validate before calling

// Lint: check that query declarations don't use inner doc comments.
// In your editor, search for '//!' lines inside rustc_queries! blocks.
// Or programmatically:
//   rg '//!' -B2 -A5 --type rust | grep -B5 'query \|non_query '
// Any match likely indicates an inner doc comment on a query.

Try / catch

// Compile-time error from the proc macro — cannot be caught.
// Fix by changing //! to ///.

Prevention

When it happens

Trigger: Writing //! instead of /// in front of a query or non_query declaration inside a rustc_queries! { } block. For example, accidentally using a module-level doc comment style on a query.

Common situations: Editor auto-completing //! because the query block is inside a module; copy-paste from module-level documentation; unfamiliarity with the difference between /// and //! in this context.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/0eee84e703bab76e. Report an issue: GitHub.

Appendix: source

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

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 }
/// //    ^^^^^^^^                               name
/// //             ^^^                           key_pat

View on GitHub (pinned to 7088e4b63a)