{"id":"db0b1887a1e07e1a","repo":"rust-lang/rust","slug":"duplicate-modifier","errorCode":null,"errorMessage":"duplicate modifier","messagePattern":"duplicate modifier","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"compiler/rustc_macros/src/query.rs","lineNumber":172,"sourceCode":"    let mut arena_cache = None;\n    let mut cache_on_disk = None;\n    let mut depth_limit = None;\n    let mut desc = None;\n    let mut eval_always = None;\n    let mut feedable = None;\n    let mut handle_cycle_error = None;\n    let mut no_force = None;\n    let mut no_hash = None;\n    let mut separate_provide_extern = None;\n    // tidy-alphabetical-end\n\n    while !input.is_empty() {\n        let modifier: Ident = input.parse()?;\n\n        macro_rules! try_insert {\n            ($name:ident = $expr:expr) => {\n                if $name.is_some() {\n                    return Err(Error::new(modifier.span(), \"duplicate modifier\"));\n                }\n                $name = Some($expr);\n            };\n        }\n\n        if modifier == \"arena_cache\" {\n            try_insert!(arena_cache = modifier);\n        } else if modifier == \"cache_on_disk\" {\n            try_insert!(cache_on_disk = modifier);\n        } else if modifier == \"depth_limit\" {\n            try_insert!(depth_limit = modifier);\n        } else if modifier == \"desc\" {\n            // Parse a description modifier like:\n            // `desc { \"foo {}\", tcx.item_path(key) }`\n            let attr_content;\n            braced!(attr_content in input);\n            let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?;\n            try_insert!(desc = Desc { modifier, expr_list });","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_macros/src/query.rs#L154-L190","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the query declaration at the reported span and remove the duplicate modifier keyword so each appears at most once.","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.","If you meant two different behaviors, verify the modifier name is correct; consult the modifier docs rather than reusing the same one twice."],"exampleFix":"// before\nquery type_of(key: DefId) -> Ty<'tcx> {\n    eval_always\n    desc { \"type of `{}`\", tcx.def_path_str(key) }\n    eval_always\n}\n\n// after\nquery type_of(key: DefId) -> Ty<'tcx> {\n    eval_always\n    desc { \"type of `{}`\", tcx.def_path_str(key) }\n}","handlingStrategy":"validation","validationCode":"// Lint your #[query(...)] modifier list before compiling\nuse std::collections::HashSet;\nfn first_duplicate(mods: &[&str]) -> Option<&str> {\n    let mut seen = HashSet::new();\n    for m in mods { if !seen.insert(*m) { return Some(*m); } }\n    None\n}\n// assert!(first_duplicate(&[\"eval_always\",\"anon\",\"eval_always\"]).is_none());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep all query modifiers in one const slice and diff it in CI before building","Add a grep-based check that no modifier keyword appears twice inside a single #[query(...)]","Re-read compiler/rustc_macros/src/query.rs:172 when adding a new modifier to confirm its semantics"],"tags":["rustc-internals","proc-macro","query-system","compile-error"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}