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

duplicate modifier

Error message

duplicate modifier

What it means

Thrown by the rustc_queries proc-macro (via the try_insert! macro at query.rs:169-176) when the same query modifier name appears more than once inside a query's modifier braces. The rustc compiler declares queries with a fixed set of modifiers (arena_cache, cache_on_disk, depth_limit, desc, eval_always, feedable, handle_cycle_error, no_force, no_hash, separate_provide_extern), each tracked as an Option<Ident>; assigning one twice is a logic error in the query declaration. The span reported is that of the duplicated modifier ident, pointing at the offending token in the query definition.

Source

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

    let mut arena_cache = None;
    let mut cache_on_disk = None;
    let mut depth_limit = None;
    let mut desc = None;
    let mut eval_always = None;
    let mut feedable = None;
    let mut handle_cycle_error = None;
    let mut no_force = None;
    let mut no_hash = None;
    let mut separate_provide_extern = None;
    // tidy-alphabetical-end

    while !input.is_empty() {
        let modifier: Ident = input.parse()?;

        macro_rules! try_insert {
            ($name:ident = $expr:expr) => {
                if $name.is_some() {
                    return Err(Error::new(modifier.span(), "duplicate modifier"));
                }
                $name = Some($expr);
            };
        }

        if modifier == "arena_cache" {
            try_insert!(arena_cache = modifier);
        } else if modifier == "cache_on_disk" {
            try_insert!(cache_on_disk = modifier);
        } else if modifier == "depth_limit" {
            try_insert!(depth_limit = modifier);
        } else if modifier == "desc" {
            // Parse a description modifier like:
            // `desc { "foo {}", tcx.item_path(key) }`
            let attr_content;
            braced!(attr_content in input);
            let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;
            try_insert!(desc = Desc { modifier, expr_list });

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Inspect the query declaration at the reported span and remove the duplicate modifier keyword so each appears at most once.
  2. Cross-check the modifier list against the canonical set documented in rustc_middle::query::modifiers (query.rs:136-150) to confirm the intended single usage.
  3. If you meant two different behaviors, verify the modifier name is correct; consult the modifier docs rather than reusing the same one twice.

Example fix

// before
query type_of(key: DefId) -> Ty<'tcx> {
    eval_always
    desc { "type of `{}`", tcx.def_path_str(key) }
    eval_always
}

// after
query type_of(key: DefId) -> Ty<'tcx> {
    eval_always
    desc { "type of `{}`", tcx.def_path_str(key) }
}
Defensive patterns

Strategy: validation

Validate before calling

// Lint your #[query(...)] modifier list before compiling
use std::collections::HashSet;
fn first_duplicate(mods: &[&str]) -> Option<&str> {
    let mut seen = HashSet::new();
    for m in mods { if !seen.insert(*m) { return Some(*m); } }
    None
}
// assert!(first_duplicate(&["eval_always","anon","eval_always"]).is_none());

Prevention

When it happens

Trigger: Authoring or editing a query in a rustc_queries! {} invocation (e.g. in compiler/rustc_middle/src/query/system.rs or similar) and listing the same modifier keyword twice in the braces block, e.g. `query foo(key: K) -> V { eval_always, desc {"x"}, eval_always }`. The parser loops over modifiers (query.rs:166) and try_insert! (line 171) rejects the second occurrence because the Option is already Some.

Common situations: Editing the rustc query system during compiler development; merging query declarations where a modifier was copy-pasted; typos that duplicate a flag like no_hash/no_force. Seen only by people hacking on the compiler internals, never by end users compiling normal crates.

Related errors


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