diff options
| -rw-r--r-- | compiler/rustc_attr/src/builtin.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 22 | ||||
| -rw-r--r-- | src/test/ui/check-cfg/invalid-cfg-value.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/check-cfg/mix.rs | 50 | ||||
| -rw-r--r-- | src/test/ui/check-cfg/mix.stderr | 66 | ||||
| -rw-r--r-- | src/test/ui/check-cfg/no-values.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/check-cfg/no-values.stderr | 11 |
9 files changed, 184 insertions, 55 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 503e172b687..50eb6b6e5da 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -462,7 +462,8 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat true } MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let name = cfg.ident().expect("multi-segment cfg predicate").name; + let ident = cfg.ident().expect("multi-segment cfg predicate"); + let name = ident.name; let value = cfg.value_str(); if let Some(names_valid) = &sess.check_config.names_valid { if !names_valid.contains(&name) { @@ -471,30 +472,24 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat cfg.span, CRATE_NODE_ID, "unexpected `cfg` condition name", - BuiltinLintDiagnostics::UnexpectedCfg( - cfg.ident().unwrap().span, - name, - None, - ), + BuiltinLintDiagnostics::UnexpectedCfg(ident.span, name, None), ); } } - if let Some(val) = value { - if let Some(values_valid) = &sess.check_config.values_valid { - if let Some(values) = values_valid.get(&name) { - if !values.contains(&val) { - sess.buffer_lint_with_diagnostic( - UNEXPECTED_CFGS, - cfg.span, - CRATE_NODE_ID, - "unexpected `cfg` condition value", - BuiltinLintDiagnostics::UnexpectedCfg( - cfg.name_value_literal_span().unwrap(), - name, - Some(val), - ), - ); - } + if let Some(value) = value { + if let Some(values) = &sess.check_config.values_valid.get(&name) { + if !values.contains(&value) { + sess.buffer_lint_with_diagnostic( + UNEXPECTED_CFGS, + cfg.span, + CRATE_NODE_ID, + "unexpected `cfg` condition value", + BuiltinLintDiagnostics::UnexpectedCfg( + cfg.name_value_literal_span().unwrap(), + name, + Some(value), + ), + ); } } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5e0d59bf1b1..91ced2a2d90 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -183,12 +183,10 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { } else if meta_item.has_name(sym::values) { if let Some((name, values)) = args.split_first() { if name.is_word() && name.ident().is_some() { - let values_valid = cfg - .values_valid - .get_or_insert_with(|| FxHashMap::default()); let ident = name.ident().expect("multi-segment cfg key"); - let ident_values = values_valid - .entry(ident.to_string()) + let ident_values = cfg + .values_valid + .entry(ident.name.to_string()) .or_insert_with(|| FxHashSet::default()); for val in values { @@ -225,10 +223,8 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { ); } - if let Some(values_valid) = &cfg.values_valid { - if let Some(names_valid) = &mut cfg.names_valid { - names_valid.extend(values_valid.keys().cloned()); - } + if let Some(names_valid) = &mut cfg.names_valid { + names_valid.extend(cfg.values_valid.keys().cloned()); } cfg }) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 72a3f5d5fc9..5f07cf08c2e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -768,17 +768,14 @@ pub trait LintContext: Sized { db.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information"); }, BuiltinLintDiagnostics::UnexpectedCfg(span, name, value) => { - let mut possibilities: Vec<Symbol> = if value.is_some() { - let Some(values_valid) = &sess.parse_sess.check_config.values_valid else { - bug!("it shouldn't be possible to have a diagnostic on a value if values checking is not enable"); - }; - let Some(values) = values_valid.get(&name) else { + let possibilities: Vec<Symbol> = if value.is_some() { + let Some(values) = &sess.parse_sess.check_config.values_valid.get(&name) else { bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values"); }; values.iter().map(|&s| s).collect() } else { let Some(names_valid) = &sess.parse_sess.check_config.names_valid else { - bug!("it shouldn't be possible to have a diagnostic on a value if values checking is not enable"); + bug!("it shouldn't be possible to have a diagnostic on a name if name checking is not enabled"); }; names_valid.iter().map(|s| *s).collect() }; @@ -786,17 +783,21 @@ pub trait LintContext: Sized { // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long if value.is_some() { - // Sorting can take some time, so we only do it if required - possibilities.sort(); + if !possibilities.is_empty() { + let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>(); + possibilities.sort(); - let possibilities = possibilities.iter().map(Symbol::as_str).intersperse(", ").collect::<String>(); - db.note(&format!("possible values for `{name}` are: {possibilities}")); + let possibilities = possibilities.join(", "); + db.note(&format!("expected values for `{name}` are: {possibilities}")); + } else { + db.note(&format!("no expected value for `{name}`")); + } } // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, value.unwrap_or(name), None) { - let ponctuation = if value.is_some() { "\"" } else { "" }; - db.span_suggestion(span, "did you mean", format!("{ponctuation}{best_match}{ponctuation}"), Applicability::MaybeIncorrect); + let punctuation = if value.is_some() { "\"" } else { "" }; + db.span_suggestion(span, "did you mean", format!("{punctuation}{best_match}{punctuation}"), Applicability::MaybeIncorrect); } }, } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e0a3cc78b17..f9b75690e37 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1023,10 +1023,10 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig /// The parsed `--check-cfg` options pub struct CheckCfg<T = String> { - /// The set of all `names()`, if none no names checking is performed + /// The set of all `names()`, if None no name checking is performed pub names_valid: Option<FxHashSet<T>>, - /// The set of all `values()`, if none no values chcking is performed - pub values_valid: Option<FxHashMap<T, FxHashSet<T>>>, + /// The set of all `values()` + pub values_valid: FxHashMap<T, FxHashSet<T>>, } impl<T> Default for CheckCfg<T> { @@ -1042,9 +1042,11 @@ impl<T> CheckCfg<T> { .names_valid .as_ref() .map(|names_valid| names_valid.iter().map(|a| f(a)).collect()), - values_valid: self.values_valid.as_ref().map(|values_valid| { - values_valid.iter().map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())).collect() - }), + values_valid: self + .values_valid + .iter() + .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())) + .collect(), } } } @@ -1098,11 +1100,9 @@ impl CrateCheckConfig { names_valid.insert(k); } if let Some(v) = v { - if let Some(values_valid) = &mut self.values_valid { - values_valid.entry(k).and_modify(|values| { - values.insert(v); - }); - } + self.values_valid.entry(k).and_modify(|values| { + values.insert(v); + }); } } } diff --git a/src/test/ui/check-cfg/invalid-cfg-value.stderr b/src/test/ui/check-cfg/invalid-cfg-value.stderr index 23fd5c8c759..bc2c053fed6 100644 --- a/src/test/ui/check-cfg/invalid-cfg-value.stderr +++ b/src/test/ui/check-cfg/invalid-cfg-value.stderr @@ -5,7 +5,7 @@ LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^^^^^^^^ | = note: `#[warn(unexpected_cfgs)]` on by default - = note: possible values for `feature` are: rand, serde, full + = note: expected values for `feature` are: full, rand, serde warning: 1 warning emitted diff --git a/src/test/ui/check-cfg/mix.rs b/src/test/ui/check-cfg/mix.rs new file mode 100644 index 00000000000..26c735c4a10 --- /dev/null +++ b/src/test/ui/check-cfg/mix.rs @@ -0,0 +1,50 @@ +// This test checks the combination of well known names, their activation via names(), the usage of +// partial values() with a --cfg and test that we also correctly lint on the `cfg!` macro and +// `cfg_attr` attribute. +// +// check-pass +// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options + +#[cfg(windows)] +fn do_windows_stuff() {} + +#[cfg(widnows)] +//~^ WARNING unexpected `cfg` condition name +fn do_windows_stuff() {} + +#[cfg(feature = "foo")] +fn use_foo() {} + +#[cfg(feature = "bar")] +fn use_bar() {} + +#[cfg(feature = "zebra")] +//~^ WARNING unexpected `cfg` condition value +fn use_zebra() {} + +#[cfg_attr(uu, test)] +//~^ WARNING unexpected `cfg` condition name +fn do_test() {} + +#[cfg_attr(feature = "foo", no_mangle)] +fn do_test_foo() {} + +fn test_cfg_macro() { + cfg!(windows); + cfg!(widnows); + //~^ WARNING unexpected `cfg` condition name + cfg!(feature = "foo"); + cfg!(feature = "bar"); + cfg!(feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value + cfg!(xxx = "foo"); + //~^ WARNING unexpected `cfg` condition name + cfg!(xxx); + //~^ WARNING unexpected `cfg` condition name + cfg!(any(xxx, windows)); + //~^ WARNING unexpected `cfg` condition name + cfg!(any(feature = "bad", windows)); + //~^ WARNING unexpected `cfg` condition value +} + +fn main() {} diff --git a/src/test/ui/check-cfg/mix.stderr b/src/test/ui/check-cfg/mix.stderr new file mode 100644 index 00000000000..b273be77422 --- /dev/null +++ b/src/test/ui/check-cfg/mix.stderr @@ -0,0 +1,66 @@ +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:11:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: did you mean: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:21:7 + | +LL | #[cfg(feature = "zebra")] + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:25:12 + | +LL | #[cfg_attr(uu, test)] + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:34:10 + | +LL | cfg!(widnows); + | ^^^^^^^ help: did you mean: `windows` + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:38:10 + | +LL | cfg!(feature = "zebra"); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: bar, foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:40:10 + | +LL | cfg!(xxx = "foo"); + | ^^^^^^^^^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:42:10 + | +LL | cfg!(xxx); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:44:14 + | +LL | cfg!(any(xxx, windows)); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:46:14 + | +LL | cfg!(any(feature = "bad", windows)); + | ^^^^^^^^^^----- + | | + | help: did you mean: `"bar"` + | + = note: expected values for `feature` are: bar, foo + +warning: 9 warnings emitted + diff --git a/src/test/ui/check-cfg/no-values.rs b/src/test/ui/check-cfg/no-values.rs new file mode 100644 index 00000000000..2440757e52d --- /dev/null +++ b/src/test/ui/check-cfg/no-values.rs @@ -0,0 +1,10 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// compile-flags: --check-cfg=values(feature) -Z unstable-options + +#[cfg(feature = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/src/test/ui/check-cfg/no-values.stderr b/src/test/ui/check-cfg/no-values.stderr new file mode 100644 index 00000000000..ea1c9107d4c --- /dev/null +++ b/src/test/ui/check-cfg/no-values.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition value + --> $DIR/no-values.rs:6:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^^^^^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + = note: no expected value for `feature` + +warning: 1 warning emitted + |
