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

duplicate modifier

Error message

duplicate modifier

What it means

Emitted by parse_query_modifiers in the rustc_queries! macro. The parser maintains an Option<Ident> slot for each modifier key (arena_cache, cache_on_disk, depth_limit, desc, eval_always, feedable, handle_cycle_error, no_force, no_hash, separate_provide_extern). The try_insert! macro checks if the slot is already Some — if so, the second occurrence of that key triggers 'duplicate modifier' at the span of the duplicate ident.

Solutions

  1. Remove the duplicate modifier — each key can appear at most once per query.
  2. Review the full modifier block for your query and ensure each key is listed exactly once.
  3. If you need the effect of a modifier combined with something else, check rustc_middle::query::modifiers for how modifiers interact — they are designed to be mutually exclusive flags.

Example fix

// before
query foo(key: DefId) -> Ty<'tcx> {
    desc { "computes foo for `{}`", key }
    eval_always
    eval_always
}
// after: remove the duplicate
query foo(key: DefId) -> Ty<'tcx> {
    desc { "computes foo for `{}`", key }
    eval_always
}
Defensive patterns

Strategy: validation

Validate before calling

// No runtime API to validate — this is a proc-macro compile-time check.
// To prevent it, review each query's modifier block for duplicates.
// You can write a simple lint script:
const KNOWN_MODIFIERS: &[&str] = &[
    "arena_cache", "cache_on_disk", "depth_limit", "desc",
    "eval_always", "feedable", "handle_cycle_error",
    "no_force", "no_hash", "separate_provide_extern",
];
// Parse each query block and assert no modifier appears more than once.

Try / catch

// Compile-time error — cannot be caught at runtime.
// Fix by removing the duplicate modifier entry.

Prevention

When it happens

Trigger: Writing a query modifier block where the same modifier key appears twice. Example: query foo(key: K) -> V { desc { "..." }, eval_always, eval_always } — the second eval_always is the duplicate.

Common situations: Copy-pasting a modifier line and forgetting to delete the original; refactoring a query's modifiers and leaving a stale entry; merge conflicts resolved by keeping both sides' modifier.

Related errors


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

Appendix: 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 7088e4b63a)