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
- Remove the duplicate modifier — each key can appear at most once per query.
- Review the full modifier block for your query and ensure each key is listed exactly once.
- 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
- Each query modifier key can appear at most once per query block.
- When refactoring modifiers, diff the before/after to spot unintended duplicates.
- Keep modifiers in the alphabetical order shown in the tidy comments for easier review.
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
- attributes must be outer attributes (`///`), not inner…
- attributes not supported on queries
- Expected a string literal
- unknown query modifier
- CFG_RELEASE env var
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)