From 4e019ac160fa96628016bc308a2bccd8962a3513 Mon Sep 17 00:00:00 2001 From: Sasha Pourcelot Date: Sun, 29 Mar 2026 10:32:11 +0000 Subject: [PATCH] make `cfg` parser suggest `any` or `all` on `#[cfg(a, b)]` --- .../rustc_attr_parsing/src/attributes/cfg.rs | 31 ++++++++++++- tests/rustdoc-ui/doc-cfg.stderr | 32 ++++++++++++++ tests/rustdoc-ui/invalid-cfg.stderr | 44 +++++++++++++++++++ tests/ui/cfg/suggest-any-or-all.stderr | 24 +++++++--- .../cfg-attr-syntax-validation.stderr | 24 +++++++--- 5 files changed, 142 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index c3b693425a52..ccc4a1a64c56 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -48,8 +48,37 @@ pub fn parse_cfg( cx.adcx().expected_list(attr_span, args); return None; }; + let Some(single) = list.single() else { - cx.adcx().expected_single_argument(list.span); + let target = cx.target; + let mut adcx = cx.adcx(); + if list.is_empty() { + // `#[cfg()]` + let message = format!("if the {target} should be disabled, use `#[cfg(false)]`"); + adcx.push_suggestion(message, list.span, "(false)".to_string()); + } else { + // `#[cfg(foo, bar)]` + if let Ok(args) = adcx + .sess() + .source_map() + .span_to_source(list.span, |src, start, end| Ok(src[start..end].to_string())) + { + let all = format!("(all{args})"); + let any = format!("(any{args})"); + + let all_msg = format!( + "if the {target} should be enabled when all these predicates are, wrap them in `all`" + ); + let any_msg = format!( + "alternately, if the {target} should be enabled when any of these predicates are, wrap them in `any`" + ); + + adcx.push_suggestion(all_msg, list.span, all); + adcx.push_suggestion(any_msg, list.span, any); + } + } + + adcx.expected_single_argument(list.span); return None; }; parse_cfg_entry(cx, single).ok() diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr index fa25a441e9b7..db525ca7a807 100644 --- a/tests/rustdoc-ui/doc-cfg.stderr +++ b/tests/rustdoc-ui/doc-cfg.stderr @@ -5,6 +5,11 @@ LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^--^^^^^^^^^^^^^^^^^ | | | expected a single argument here + | +help: if the function should be disabled, use `#[cfg(false)]` + | +LL | #[doc(cfg(false), cfg(foo, bar))] + | +++++ error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:4:1 @@ -13,6 +18,17 @@ LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^^^^^^^^----------^^ | | | expected a single argument here + | +help: if the function should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(), cfg(foo, bar))] +LL + #[doc(cfg(), cfg(all(foo, bar)))] + | +help: alternately, if the function should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(), cfg(foo, bar))] +LL + #[doc(cfg(), cfg(any(foo, bar)))] + | error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:7:1 @@ -21,6 +37,11 @@ LL | #[doc(cfg())] | ^^^^^^^^^--^^ | | | expected a single argument here + | +help: if the function should be disabled, use `#[cfg(false)]` + | +LL | #[doc(cfg(false))] + | +++++ error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:8:1 @@ -29,6 +50,17 @@ LL | #[doc(cfg(foo, bar))] | ^^^^^^^^^----------^^ | | | expected a single argument here + | +help: if the function should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(foo, bar))] +LL + #[doc(cfg(all(foo, bar)))] + | +help: alternately, if the function should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(foo, bar))] +LL + #[doc(cfg(any(foo, bar)))] + | error: aborting due to 4 previous errors diff --git a/tests/rustdoc-ui/invalid-cfg.stderr b/tests/rustdoc-ui/invalid-cfg.stderr index 539611070969..60b403371362 100644 --- a/tests/rustdoc-ui/invalid-cfg.stderr +++ b/tests/rustdoc-ui/invalid-cfg.stderr @@ -13,6 +13,17 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here + | +help: if the struct should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(all(x, y)))] + | +help: alternately, if the struct should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(any(x, y)))] + | error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:7:1 @@ -29,6 +40,17 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here + | +help: if the struct should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(all(x, y)))] + | +help: alternately, if the struct should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(any(x, y)))] + | error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:12:1 @@ -45,6 +67,17 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here + | +help: if the struct should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(all(x, y)))] + | +help: alternately, if the struct should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(any(x, y)))] + | error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:18:1 @@ -61,6 +94,17 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here + | +help: if the struct should be enabled when all these predicates are, wrap them in `all` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(all(x, y)))] + | +help: alternately, if the struct should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[doc(cfg(x, y))] +LL + #[doc(cfg(any(x, y)))] + | error: aborting due to 8 previous errors diff --git a/tests/ui/cfg/suggest-any-or-all.stderr b/tests/ui/cfg/suggest-any-or-all.stderr index 596a49f26103..67ff6f178d12 100644 --- a/tests/ui/cfg/suggest-any-or-all.stderr +++ b/tests/ui/cfg/suggest-any-or-all.stderr @@ -3,22 +3,34 @@ error[E0805]: malformed `cfg` attribute input | LL | #[cfg(foo, bar)] | ^^^^^----------^ - | | | - | | expected a single argument here - | help: must be of the form: `#[cfg(predicate)]` + | | + | expected a single argument here | = note: for more information, visit +help: if the crate should be enabled when all these predicates are, wrap them in `all` + | +LL - #[cfg(foo, bar)] +LL + #[cfg(all(foo, bar))] + | +help: alternately, if the crate should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[cfg(foo, bar)] +LL + #[cfg(any(foo, bar))] + | error[E0805]: malformed `cfg` attribute input --> $DIR/suggest-any-or-all.rs:5:1 | LL | #[cfg()] | ^^^^^--^ - | | | - | | expected a single argument here - | help: must be of the form: `#[cfg(predicate)]` + | | + | expected a single argument here | = note: for more information, visit +help: if the crate should be disabled, use `#[cfg(false)]` + | +LL | #[cfg(false)] + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 1be52de708e5..ddb5cd84097f 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -25,22 +25,34 @@ error[E0805]: malformed `cfg` attribute input | LL | #[cfg()] | ^^^^^--^ - | | | - | | expected a single argument here - | help: must be of the form: `#[cfg(predicate)]` + | | + | expected a single argument here | = note: for more information, visit +help: if the crate should be disabled, use `#[cfg(false)]` + | +LL | #[cfg(false)] + | +++++ error[E0805]: malformed `cfg` attribute input --> $DIR/cfg-attr-syntax-validation.rs:19:1 | LL | #[cfg(a, b)] | ^^^^^------^ - | | | - | | expected a single argument here - | help: must be of the form: `#[cfg(predicate)]` + | | + | expected a single argument here | = note: for more information, visit +help: if the crate should be enabled when all these predicates are, wrap them in `all` + | +LL - #[cfg(a, b)] +LL + #[cfg(all(a, b))] + | +help: alternately, if the crate should be enabled when any of these predicates are, wrap them in `any` + | +LL - #[cfg(a, b)] +LL + #[cfg(any(a, b))] + | error[E0539]: malformed `cfg` attribute input --> $DIR/cfg-attr-syntax-validation.rs:25:1