From ad6f4b73ebfc26859a3a6b70b3790ab55d285440 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Apr 2023 11:51:36 +0200 Subject: [PATCH 1/4] Use explicit instead of implicit control-flow for check-cfg parsing --- compiler/rustc_interface/src/interface.rs | 63 ++++++++++++++--------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8e9150ba8ad3d..de24a25f1336e 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -13,7 +13,8 @@ use rustc_middle::ty; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; -use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilenames}; +use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; +use rustc_session::config::{CheckCfg, ExpectedValues}; use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::Session; @@ -121,9 +122,9 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option) -> CheckCfg { rustc_span::create_default_session_if_not_set_then(move |_| { - let mut cfg = CheckCfg::default(); + let mut check_cfg = CheckCfg::default(); - 'specs: for s in specs { + for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" ))); @@ -137,17 +138,24 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s ), - ); + ) }; } + let expected_error = || { + error!( + "expected `names(name1, name2, ... nameN)` or \ + `values(name, \"value1\", \"value2\", ... \"valueN\")`" + ) + }; + match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { Ok(mut parser) => match parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { if let Some(args) = meta_item.meta_item_list() { if meta_item.has_name(sym::names) { let names_valid = - cfg.names_valid.get_or_insert_with(|| FxHashSet::default()); + check_cfg.names_valid.get_or_insert_with(|| FxHashSet::default()); for arg in args { if arg.is_word() && arg.ident().is_some() { let ident = arg.ident().expect("multi-segment cfg key"); @@ -156,15 +164,20 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { error!("`names()` arguments must be simple identifiers"); } } - continue 'specs; } 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 ident = name.ident().expect("multi-segment cfg key"); - let ident_values = cfg + let ident_values = check_cfg .values_valid .entry(ident.name.to_string()) - .or_insert_with(|| FxHashSet::default()); + .or_insert_with(|| { + ExpectedValues::Some(FxHashSet::default()) + }); + + let ExpectedValues::Some(expected_values) = expected_values else { + bug!("shoudn't be possible") + }; for val in values { if let Some(LitKind::Str(s, _)) = @@ -177,36 +190,40 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { ); } } - - continue 'specs; } else { error!( "`values()` first argument must be a simple identifier" ); } } else if args.is_empty() { - cfg.well_known_values = true; - continue 'specs; + check_cfg.well_known_values = true; + } else { + expected_error(); } + } else { + expected_error(); } + } else { + expected_error(); } } - Ok(..) => {} - Err(err) => err.cancel(), + Ok(..) => expected_error(), + Err(err) => { + err.cancel(); + expected_error(); + } }, - Err(errs) => drop(errs), + Err(errs) => { + drop(errs); + expected_error(); + } } - - error!( - "expected `names(name1, name2, ... nameN)` or \ - `values(name, \"value1\", \"value2\", ... \"valueN\")`" - ); } - if let Some(names_valid) = &mut cfg.names_valid { - names_valid.extend(cfg.values_valid.keys().cloned()); + if let Some(names_valid) = &mut check_cfg.names_valid { + names_valid.extend(check_cfg.values_valid.keys().cloned()); } - cfg + check_cfg }) } From d327d5b16840346d838a29fdbac49a66be216a08 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Apr 2023 14:43:59 +0200 Subject: [PATCH 2/4] Improve internal representation of check-cfg This is done to simplify to relationship between names() and values() but also make thing clearer (having an Any to represent that any values are allowed) but also to allow the (none) + values expected cases that wasn't possible before. --- compiler/rustc_attr/src/builtin.rs | 34 ++-- compiler/rustc_interface/src/interface.rs | 25 ++- compiler/rustc_lint/src/builtin.rs | 20 +- compiler/rustc_lint/src/context.rs | 14 +- compiler/rustc_session/src/config.rs | 233 ++++++++++++---------- 5 files changed, 173 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index d2d3792345f1c..70426d8607520 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -5,6 +5,7 @@ use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedM use rustc_ast_pretty::pprust; use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; use rustc_macros::HashStable_Generic; +use rustc_session::config::ExpectedValues; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; @@ -581,8 +582,20 @@ pub fn cfg_matches( ) -> bool { eval_condition(cfg, sess, features, &mut |cfg| { try_gate_cfg(cfg.name, cfg.span, sess, features); - if let Some(names_valid) = &sess.check_config.names_valid { - if !names_valid.contains(&cfg.name) { + match sess.check_config.expecteds.get(&cfg.name) { + Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => { + sess.buffer_lint_with_diagnostic( + UNEXPECTED_CFGS, + cfg.span, + lint_node_id, + "unexpected `cfg` condition value", + BuiltinLintDiagnostics::UnexpectedCfg( + (cfg.name, cfg.name_span), + cfg.value_span.map(|vs| (cfg.value.unwrap(), vs)), + ), + ); + } + None if sess.check_config.exhaustive_names => { sess.buffer_lint_with_diagnostic( UNEXPECTED_CFGS, cfg.span, @@ -591,22 +604,7 @@ pub fn cfg_matches( BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None), ); } - } - if let Some(value) = cfg.value { - if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) { - if !values.contains(&value) { - sess.buffer_lint_with_diagnostic( - UNEXPECTED_CFGS, - cfg.span, - lint_node_id, - "unexpected `cfg` condition value", - BuiltinLintDiagnostics::UnexpectedCfg( - (cfg.name, cfg.name_span), - cfg.value_span.map(|vs| (value, vs)), - ), - ); - } - } + _ => { /* not unexpected */ } } sess.config.contains(&(cfg.name, cfg.value)) }) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index de24a25f1336e..9d9f4ee13f402 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -9,7 +9,7 @@ use rustc_data_structures::OnDrop; use rustc_errors::registry::Registry; use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_lint::LintStore; -use rustc_middle::ty; +use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; @@ -154,12 +154,14 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { Ok(meta_item) if parser.token == token::Eof => { if let Some(args) = meta_item.meta_item_list() { if meta_item.has_name(sym::names) { - let names_valid = - check_cfg.names_valid.get_or_insert_with(|| FxHashSet::default()); + check_cfg.exhaustive_names = true; for arg in args { if arg.is_word() && arg.ident().is_some() { let ident = arg.ident().expect("multi-segment cfg key"); - names_valid.insert(ident.name.to_string()); + check_cfg + .expecteds + .entry(ident.name.to_string()) + .or_insert(ExpectedValues::Any); } else { error!("`names()` arguments must be simple identifiers"); } @@ -168,8 +170,8 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { if let Some((name, values)) = args.split_first() { if name.is_word() && name.ident().is_some() { let ident = name.ident().expect("multi-segment cfg key"); - let ident_values = check_cfg - .values_valid + let expected_values = check_cfg + .expecteds .entry(ident.name.to_string()) .or_insert_with(|| { ExpectedValues::Some(FxHashSet::default()) @@ -183,20 +185,24 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) { - ident_values.insert(s.to_string()); + expected_values.insert(Some(s.to_string())); } else { error!( "`values()` arguments must be string literals" ); } } + + if values.is_empty() { + expected_values.insert(None); + } } else { error!( "`values()` first argument must be a simple identifier" ); } } else if args.is_empty() { - check_cfg.well_known_values = true; + check_cfg.exhaustive_values = true; } else { expected_error(); } @@ -220,9 +226,6 @@ pub fn parse_check_cfg(specs: Vec) -> CheckCfg { } } - if let Some(names_valid) = &mut check_cfg.names_valid { - names_valid.extend(check_cfg.values_valid.keys().cloned()); - } check_cfg }) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index aeb791901bd23..010526988506d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -63,6 +63,7 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; +use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -3306,16 +3307,15 @@ impl EarlyLintPass for UnexpectedCfgs { let cfg = &cx.sess().parse_sess.config; let check_cfg = &cx.sess().parse_sess.check_config; for &(name, value) in cfg { - if let Some(names_valid) = &check_cfg.names_valid && !names_valid.contains(&name){ - cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigName { - name, - }); - } - if let Some(value) = value && let Some(values) = check_cfg.values_valid.get(&name) && !values.contains(&value) { - cx.emit_lint( - UNEXPECTED_CFGS, - BuiltinUnexpectedCliConfigValue { name, value }, - ); + match check_cfg.expecteds.get(&name) { + Some(ExpectedValues::Some(values)) if !values.contains(&value) => { + let value = value.unwrap_or(kw::Empty); + cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigValue { name, value }); + } + None if check_cfg.exhaustive_names => { + cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigName { name }); + } + _ => { /* expected */ } } } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index d4898ffe883bc..f53a7bb0c19db 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -769,10 +769,7 @@ pub trait LintContext: Sized { db.note("see the asm section of Rust By Example for more information"); }, BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), None) => { - let Some(names_valid) = &sess.parse_sess.check_config.names_valid else { - bug!("it shouldn't be possible to have a diagnostic on a name if name checking is not enabled"); - }; - let possibilities: Vec = names_valid.iter().map(|s| *s).collect(); + let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().map(|s| *s).collect(); // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { @@ -780,10 +777,15 @@ pub trait LintContext: Sized { } }, BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), Some((value, value_span))) => { - let Some(values) = &sess.parse_sess.check_config.values_valid.get(&name) else { + let Some(rustc_session::config::ExpectedValues::Some(values)) = &sess.parse_sess.check_config.expecteds.get(&name) else { bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values"); }; - let possibilities: Vec = values.iter().map(|&s| s).collect(); + let mut have_none_possibility = false; + let possibilities: Vec = values.iter() + .inspect(|a| have_none_possibility |= a.is_none()) + .copied() + .filter_map(std::convert::identity) + .collect(); // 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 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 51418c01eedb4..e731fde6c3c6d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1056,37 +1056,76 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option)>) -> CrateConfig /// The parsed `--check-cfg` options pub struct CheckCfg { - /// The set of all `names()`, if None no name checking is performed - pub names_valid: Option>, + /// Is well known names activated + pub exhaustive_names: bool, /// Is well known values activated - pub well_known_values: bool, - /// The set of all `values()` - pub values_valid: FxHashMap>, + pub exhaustive_values: bool, + /// All the expected values for a config name + pub expecteds: FxHashMap>, } impl Default for CheckCfg { fn default() -> Self { CheckCfg { - names_valid: Default::default(), - values_valid: Default::default(), - well_known_values: false, + exhaustive_names: false, + exhaustive_values: false, + expecteds: FxHashMap::default(), } } } impl CheckCfg { - fn map_data(&self, f: impl Fn(&T) -> O) -> CheckCfg { + fn map_data(self, f: impl Fn(T) -> O) -> CheckCfg { CheckCfg { - names_valid: self - .names_valid - .as_ref() - .map(|names_valid| names_valid.iter().map(|a| f(a)).collect()), - values_valid: self - .values_valid - .iter() - .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())) + exhaustive_names: self.exhaustive_names, + exhaustive_values: self.exhaustive_values, + expecteds: self + .expecteds + .into_iter() + .map(|(name, values)| { + ( + f(name), + match values { + ExpectedValues::Some(values) => ExpectedValues::Some( + values.into_iter().map(|b| b.map(|b| f(b))).collect(), + ), + ExpectedValues::Any => ExpectedValues::Any, + }, + ) + }) .collect(), - well_known_values: self.well_known_values, + } + } +} + +pub enum ExpectedValues { + Some(FxHashSet>), + Any, +} + +impl ExpectedValues { + fn insert(&mut self, value: T) -> bool { + match self { + ExpectedValues::Some(expecteds) => expecteds.insert(Some(value)), + ExpectedValues::Any => false, + } + } +} + +impl Extend for ExpectedValues { + fn extend>(&mut self, iter: I) { + match self { + ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(Some)), + ExpectedValues::Any => {} + } + } +} + +impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues { + fn extend>(&mut self, iter: I) { + match self { + ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(|a| Some(*a))), + ExpectedValues::Any => {} } } } @@ -1095,58 +1134,27 @@ impl CheckCfg { /// `rustc_interface::interface::Config` accepts this in the compiler configuration, /// but the symbol interner is not yet set up then, so we must convert it later. pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig { - cfg.map_data(|s| Symbol::intern(s)) + cfg.map_data(|s| Symbol::intern(&s)) } impl CrateCheckConfig { - /// Fills a `CrateCheckConfig` with well-known configuration names. - fn fill_well_known_names(&mut self) { - // NOTE: This should be kept in sync with `default_configuration` and - // `fill_well_known_values` - const WELL_KNOWN_NAMES: &[Symbol] = &[ - // rustc - sym::unix, - sym::windows, - sym::target_os, - sym::target_family, - sym::target_arch, - sym::target_endian, - sym::target_pointer_width, - sym::target_env, - sym::target_abi, - sym::target_vendor, - sym::target_thread_local, - sym::target_has_atomic_load_store, - sym::target_has_atomic, - sym::target_has_atomic_equal_alignment, - sym::target_feature, - sym::panic, - sym::sanitize, - sym::debug_assertions, - sym::proc_macro, - sym::test, - sym::feature, - // rustdoc - sym::doc, - sym::doctest, - // miri - sym::miri, - ]; - - // We only insert well-known names if `names()` was activated - if let Some(names_valid) = &mut self.names_valid { - names_valid.extend(WELL_KNOWN_NAMES); - } - } - - /// Fills a `CrateCheckConfig` with well-known configuration values. - fn fill_well_known_values(&mut self, current_target: &Target) { - if !self.well_known_values { + pub fn fill_well_known(&mut self, current_target: &Target) { + if !self.exhaustive_values && !self.exhaustive_names { return; } - // NOTE: This should be kept in sync with `default_configuration` and - // `fill_well_known_names` + let no_values = || { + let mut values = FxHashSet::default(); + values.insert(None); + ExpectedValues::Some(values) + }; + + let empty_values = || { + let values = FxHashSet::default(); + ExpectedValues::Some(values) + }; + + // NOTE: This should be kept in sync with `default_configuration` let panic_values = &PanicStrategy::all(); @@ -1166,6 +1174,9 @@ impl CrateCheckConfig { // Unknown possible values: // - `feature` // - `target_feature` + for name in [sym::feature, sym::target_feature] { + self.expecteds.entry(name).or_insert(ExpectedValues::Any); + } // No-values for name in [ @@ -1179,20 +1190,23 @@ impl CrateCheckConfig { sym::debug_assertions, sym::target_thread_local, ] { - self.values_valid.entry(name).or_default(); + self.expecteds.entry(name).or_insert_with(no_values); } // Pre-defined values - self.values_valid.entry(sym::panic).or_default().extend(panic_values); - self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values); - self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values); - self.values_valid + self.expecteds.entry(sym::panic).or_insert_with(empty_values).extend(panic_values); + self.expecteds.entry(sym::sanitize).or_insert_with(empty_values).extend(sanitize_values); + self.expecteds + .entry(sym::target_has_atomic) + .or_insert_with(no_values) + .extend(atomic_values); + self.expecteds .entry(sym::target_has_atomic_load_store) - .or_default() + .or_insert_with(no_values) .extend(atomic_values); - self.values_valid + self.expecteds .entry(sym::target_has_atomic_equal_alignment) - .or_default() + .or_insert_with(no_values) .extend(atomic_values); // Target specific values @@ -1210,47 +1224,50 @@ impl CrateCheckConfig { // Initialize (if not already initialized) for &e in VALUES { - self.values_valid.entry(e).or_default(); + let entry = self.expecteds.entry(e); + if !self.exhaustive_values { + entry.or_insert(ExpectedValues::Any); + } else { + entry.or_insert_with(empty_values); + } } - // Get all values map at once otherwise it would be costly. - // (8 values * 220 targets ~= 1760 times, at the time of writing this comment). - let [ - values_target_os, - values_target_family, - values_target_arch, - values_target_endian, - values_target_env, - values_target_abi, - values_target_vendor, - values_target_pointer_width, - ] = self - .values_valid - .get_many_mut(VALUES) - .expect("unable to get all the check-cfg values buckets"); - - for target in TARGETS - .iter() - .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target))) - .chain(iter::once(current_target.clone())) - { - values_target_os.insert(Symbol::intern(&target.options.os)); - values_target_family - .extend(target.options.families.iter().map(|family| Symbol::intern(family))); - values_target_arch.insert(Symbol::intern(&target.arch)); - values_target_endian.insert(Symbol::intern(target.options.endian.as_str())); - values_target_env.insert(Symbol::intern(&target.options.env)); - values_target_abi.insert(Symbol::intern(&target.options.abi)); - values_target_vendor.insert(Symbol::intern(&target.options.vendor)); - values_target_pointer_width.insert(sym::integer(target.pointer_width)); + if self.exhaustive_values { + // Get all values map at once otherwise it would be costly. + // (8 values * 220 targets ~= 1760 times, at the time of writing this comment). + let [ + values_target_os, + values_target_family, + values_target_arch, + values_target_endian, + values_target_env, + values_target_abi, + values_target_vendor, + values_target_pointer_width, + ] = self + .expecteds + .get_many_mut(VALUES) + .expect("unable to get all the check-cfg values buckets"); + + for target in TARGETS + .iter() + .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target))) + .chain(iter::once(current_target.clone())) + { + values_target_os.insert(Symbol::intern(&target.options.os)); + values_target_family.extend( + target.options.families.iter().map(|family| Symbol::intern(family)), + ); + values_target_arch.insert(Symbol::intern(&target.arch)); + values_target_endian.insert(Symbol::intern(target.options.endian.as_str())); + values_target_env.insert(Symbol::intern(&target.options.env)); + values_target_abi.insert(Symbol::intern(&target.options.abi)); + values_target_vendor.insert(Symbol::intern(&target.options.vendor)); + values_target_pointer_width.insert(sym::integer(target.pointer_width)); + } } } } - - pub fn fill_well_known(&mut self, current_target: &Target) { - self.fill_well_known_names(); - self.fill_well_known_values(current_target); - } } pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { From a5f8dba4cd7add4fc51914a98967baf4008bd2f8 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Apr 2023 15:52:44 +0200 Subject: [PATCH 3/4] Improve check-cfg diagnostics (part 1) --- compiler/rustc_attr/src/builtin.rs | 2 +- compiler/rustc_lint/src/context.rs | 16 ++++++------- tests/rustdoc-ui/check-cfg/check-cfg.stderr | 2 +- .../rustdoc-ui/doctest/check-cfg-test.stderr | 2 +- tests/ui/check-cfg/compact-values.stderr | 2 +- tests/ui/check-cfg/invalid-cfg-name.stderr | 2 +- tests/ui/check-cfg/invalid-cfg-value.stderr | 6 ++--- tests/ui/check-cfg/mix.stderr | 24 +++++++++---------- tests/ui/check-cfg/no-values.stderr | 4 +++- tests/ui/check-cfg/values-target-json.stderr | 4 ++-- tests/ui/check-cfg/well-known-names.stderr | 6 ++--- tests/ui/check-cfg/well-known-values.stderr | 8 +++---- 12 files changed, 40 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 70426d8607520..5d32080a9989c 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -591,7 +591,7 @@ pub fn cfg_matches( "unexpected `cfg` condition value", BuiltinLintDiagnostics::UnexpectedCfg( (cfg.name, cfg.name_span), - cfg.value_span.map(|vs| (cfg.value.unwrap(), vs)), + cfg.value.map(|v| (v, cfg.value_span.unwrap())), ), ); } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index f53a7bb0c19db..63c25d8f030ad 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -773,7 +773,7 @@ pub trait LintContext: Sized { // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { - db.span_suggestion(name_span, "did you mean", best_match, Applicability::MaybeIncorrect); + db.span_suggestion(name_span, "there is an config with a similar name", best_match, Applicability::MaybeIncorrect); } }, BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), Some((value, value_span))) => { @@ -794,19 +794,19 @@ pub trait LintContext: Sized { let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::>(); possibilities.sort(); - let possibilities = possibilities.join(", "); - db.note(format!("expected values for `{name}` are: {possibilities}")); + let possibilities = possibilities.join("`, `"); + let none = if have_none_possibility { "(none), " } else { "" }; + + db.note(format!("expected values for `{name}` are: {none}`{possibilities}`")); } // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) { - db.span_suggestion(value_span, "did you mean", format!("\"{best_match}\""), Applicability::MaybeIncorrect); + db.span_suggestion(value_span, "there is an expected value with a similar name", format!("\"{best_match}\""), Applicability::MaybeIncorrect); } - } else { + } else if have_none_possibility { db.note(format!("no expected value for `{name}`")); - if name != sym::feature { - db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect); - } + db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect); } }, BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => { diff --git a/tests/rustdoc-ui/check-cfg/check-cfg.stderr b/tests/rustdoc-ui/check-cfg/check-cfg.stderr index 1db8e1d91c249..03fb6f96fb5f9 100644 --- a/tests/rustdoc-ui/check-cfg/check-cfg.stderr +++ b/tests/rustdoc-ui/check-cfg/check-cfg.stderr @@ -2,7 +2,7 @@ warning: unexpected `cfg` condition name --> $DIR/check-cfg.rs:5:7 | LL | #[cfg(uniz)] - | ^^^^ help: did you mean: `unix` + | ^^^^ help: there is a config with a similar name: `unix` | = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.stderr b/tests/rustdoc-ui/doctest/check-cfg-test.stderr index 9770be2f191f0..f84543c207254 100644 --- a/tests/rustdoc-ui/doctest/check-cfg-test.stderr +++ b/tests/rustdoc-ui/doctest/check-cfg-test.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "invalid")] | ^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: test + = note: expected values for `feature` are: `test` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index 5ca4d3b3de741..70a967c0e5f64 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(target(os = "linux", arch = "X"))] | ^^^^^^^^^^ | - = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, loongarch64, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 + = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips64`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/invalid-cfg-name.stderr b/tests/ui/check-cfg/invalid-cfg-name.stderr index 2bd1821c9422b..01ee4f209f1e6 100644 --- a/tests/ui/check-cfg/invalid-cfg-name.stderr +++ b/tests/ui/check-cfg/invalid-cfg-name.stderr @@ -2,7 +2,7 @@ warning: unexpected `cfg` condition name --> $DIR/invalid-cfg-name.rs:7:7 | LL | #[cfg(widnows)] - | ^^^^^^^ help: did you mean: `windows` + | ^^^^^^^ help: there is an config with a similar name: `windows` | = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/invalid-cfg-value.stderr index 83383ea61a4ab..0ef8a06dc92e2 100644 --- a/tests/ui/check-cfg/invalid-cfg-value.stderr +++ b/tests/ui/check-cfg/invalid-cfg-value.stderr @@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- | | - | help: did you mean: `"serde"` + | help: there is an expected value with a similar name: `"serde"` | - = note: expected values for `feature` are: full, serde + = note: expected values for `feature` are: `full`, `serde` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: full, serde + = note: expected values for `feature` are: `full`, `serde` warning: unexpected condition value `rand` for condition name `feature` | diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 9cf887ec7885c..e3738af13ff5f 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -2,7 +2,7 @@ warning: unexpected `cfg` condition name --> $DIR/mix.rs:11:7 | LL | #[cfg(widnows)] - | ^^^^^^^ help: did you mean: `windows` + | ^^^^^^^ help: there is an config with a similar name: `windows` | = note: `#[warn(unexpected_cfgs)]` on by default @@ -12,7 +12,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value --> $DIR/mix.rs:22:7 @@ -20,7 +20,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name --> $DIR/mix.rs:26:12 @@ -40,7 +40,7 @@ warning: unexpected `cfg` condition name --> $DIR/mix.rs:35:10 | LL | cfg!(widnows); - | ^^^^^^^ help: did you mean: `windows` + | ^^^^^^^ help: there is an config with a similar name: `windows` warning: unexpected `cfg` condition value --> $DIR/mix.rs:38:10 @@ -48,7 +48,7 @@ warning: unexpected `cfg` condition value LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value --> $DIR/mix.rs:40:10 @@ -56,7 +56,7 @@ warning: unexpected `cfg` condition value LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name --> $DIR/mix.rs:42:10 @@ -82,7 +82,7 @@ warning: unexpected `cfg` condition value LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name --> $DIR/mix.rs:50:23 @@ -126,7 +126,7 @@ warning: unexpected `cfg` condition value LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name --> $DIR/mix.rs:62:14 @@ -140,7 +140,7 @@ warning: unexpected `cfg` condition value LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name --> $DIR/mix.rs:65:14 @@ -160,7 +160,7 @@ warning: unexpected `cfg` condition value LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value --> $DIR/mix.rs:68:33 @@ -168,7 +168,7 @@ warning: unexpected `cfg` condition value LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value --> $DIR/mix.rs:68:52 @@ -176,7 +176,7 @@ warning: unexpected `cfg` condition value LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: foo + = note: expected values for `feature` are: `foo` warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/no-values.stderr b/tests/ui/check-cfg/no-values.stderr index 8c926d187fed4..ffa87dc58f203 100644 --- a/tests/ui/check-cfg/no-values.stderr +++ b/tests/ui/check-cfg/no-values.stderr @@ -2,7 +2,9 @@ warning: unexpected `cfg` condition value --> $DIR/no-values.rs:6:7 | LL | #[cfg(feature = "foo")] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^-------- + | | + | help: remove the value | = note: no expected value for `feature` = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr index b58d2970773b8..8500fc0880503 100644 --- a/tests/ui/check-cfg/values-target-json.stderr +++ b/tests/ui/check-cfg/values-target-json.stderr @@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_os = "linuz")] | ^^^^^^^^^^^^------- | | - | help: did you mean: `"linux"` + | help: there is an expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, ericos, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vita, vxworks, wasi, watchos, windows, xous + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index bdbe4d29d30fe..987339a222a12 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name LL | #[cfg(target_oz = "linux")] | ---------^^^^^^^^^^ | | - | help: did you mean: `target_os` + | help: there is an config with a similar name: `target_os` | = note: `#[warn(unexpected_cfgs)]` on by default @@ -14,13 +14,13 @@ warning: unexpected `cfg` condition name LL | #[cfg(features = "foo")] | --------^^^^^^^^ | | - | help: did you mean: `feature` + | help: there is an config with a similar name: `feature` warning: unexpected `cfg` condition name --> $DIR/well-known-names.rs:20:7 | LL | #[cfg(uniw)] - | ^^^^ help: did you mean: `unix` + | ^^^^ help: there is an config with a similar name: `unix` warning: 3 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 69d799783a94b..4bd8e6ae09f29 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_os = "linuz")] | ^^^^^^^^^^^^------- | | - | help: did you mean: `"linux"` + | help: there is an expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vita, vxworks, wasi, watchos, windows, xous + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value @@ -15,9 +15,9 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_has_atomic = "0")] | ^^^^^^^^^^^^^^^^^^^^--- | | - | help: did you mean: `"8"` + | help: there is an expected value with a similar name: `"8"` | - = note: expected values for `target_has_atomic` are: 128, 16, 32, 64, 8, ptr + = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` warning: unexpected `cfg` condition value --> $DIR/well-known-values.rs:21:7 From 53647845b917fac2a1565c72f2046f6bbad341d6 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Apr 2023 19:09:15 +0200 Subject: [PATCH 4/4] Improve check-cfg diagnostics (part 2) --- compiler/rustc_attr/src/builtin.rs | 7 ++- compiler/rustc_lint/src/context.rs | 54 ++++++++++++++--- compiler/rustc_lint_defs/src/lib.rs | 3 +- tests/ui/check-cfg/diagnotics.rs | 31 ++++++++++ tests/ui/check-cfg/diagnotics.stderr | 62 ++++++++++++++++++++ tests/ui/check-cfg/invalid-cfg-name.stderr | 2 +- tests/ui/check-cfg/invalid-cfg-value.stderr | 2 +- tests/ui/check-cfg/mix.rs | 4 ++ tests/ui/check-cfg/mix.stderr | 62 +++++++++++--------- tests/ui/check-cfg/values-target-json.stderr | 2 +- tests/ui/check-cfg/well-known-names.stderr | 6 +- tests/ui/check-cfg/well-known-values.stderr | 4 +- 12 files changed, 192 insertions(+), 47 deletions(-) create mode 100644 tests/ui/check-cfg/diagnotics.rs create mode 100644 tests/ui/check-cfg/diagnotics.stderr diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 5d32080a9989c..2a3092d3c7b34 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -589,7 +589,7 @@ pub fn cfg_matches( cfg.span, lint_node_id, "unexpected `cfg` condition value", - BuiltinLintDiagnostics::UnexpectedCfg( + BuiltinLintDiagnostics::UnexpectedCfgValue( (cfg.name, cfg.name_span), cfg.value.map(|v| (v, cfg.value_span.unwrap())), ), @@ -601,7 +601,10 @@ pub fn cfg_matches( cfg.span, lint_node_id, "unexpected `cfg` condition name", - BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None), + BuiltinLintDiagnostics::UnexpectedCfgName( + (cfg.name, cfg.name_span), + cfg.value.map(|v| (v, cfg.value_span.unwrap())), + ), ); } _ => { /* not unexpected */ } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 63c25d8f030ad..53d7cf74cde53 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -36,6 +36,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt}; +use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; @@ -768,23 +769,51 @@ pub trait LintContext: Sized { db.help(help); db.note("see the asm section of Rust By Example for more information"); }, - BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), None) => { + BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().map(|s| *s).collect(); // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { - db.span_suggestion(name_span, "there is an config with a similar name", best_match, Applicability::MaybeIncorrect); + if let Some(ExpectedValues::Some(best_match_values)) = + sess.parse_sess.check_config.expecteds.get(&best_match) { + let mut possibilities = best_match_values.iter() + .flatten() + .map(Symbol::as_str) + .collect::>(); + possibilities.sort(); + + if let Some((value, value_span)) = value { + if best_match_values.contains(&Some(value)) { + db.span_suggestion(name_span, "there is a config with a similar name and value", best_match, Applicability::MaybeIncorrect); + } else if best_match_values.contains(&None) { + db.span_suggestion(name_span.to(value_span), "there is a config with a similar name and no value", best_match, Applicability::MaybeIncorrect); + } else if let Some(first_value) = possibilities.first() { + db.span_suggestion(name_span.to(value_span), "there is a config with a similar name and different values", format!("{best_match} = \"{first_value}\""), Applicability::MaybeIncorrect); + } else { + db.span_suggestion(name_span.to(value_span), "there is a config with a similar name and different values", best_match, Applicability::MaybeIncorrect); + }; + } else { + db.span_suggestion(name_span, "there is a config with a similar name", best_match, Applicability::MaybeIncorrect); + } + + if !possibilities.is_empty() { + let possibilities = possibilities.join("`, `"); + db.help(format!("expected values for `{best_match}` are: `{possibilities}`")); + } + } else { + db.span_suggestion(name_span, "there is a config with a similar name", best_match, Applicability::MaybeIncorrect); + } } }, - BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), Some((value, value_span))) => { - let Some(rustc_session::config::ExpectedValues::Some(values)) = &sess.parse_sess.check_config.expecteds.get(&name) else { + BuiltinLintDiagnostics::UnexpectedCfgValue((name, name_span), value) => { + let Some(ExpectedValues::Some(values)) = &sess.parse_sess.check_config.expecteds.get(&name) else { bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values"); }; let mut have_none_possibility = false; let possibilities: Vec = values.iter() .inspect(|a| have_none_possibility |= a.is_none()) .copied() - .filter_map(std::convert::identity) + .flatten() .collect(); // Show the full list if all possible values for a given name, but don't do it @@ -800,13 +829,20 @@ pub trait LintContext: Sized { db.note(format!("expected values for `{name}` are: {none}`{possibilities}`")); } - // Suggest the most probable if we found one - if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) { - db.span_suggestion(value_span, "there is an expected value with a similar name", format!("\"{best_match}\""), Applicability::MaybeIncorrect); + if let Some((value, value_span)) = value { + // Suggest the most probable if we found one + if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) { + db.span_suggestion(value_span, "there is a expected value with a similar name", format!("\"{best_match}\""), Applicability::MaybeIncorrect); + + } + } else if let &[first_possibility] = &possibilities[..] { + db.span_suggestion(name_span.shrink_to_hi(), "specify a config value", format!(" = \"{first_possibility}\""), Applicability::MaybeIncorrect); } } else if have_none_possibility { db.note(format!("no expected value for `{name}`")); - db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect); + if let Some((_value, value_span)) = value { + db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect); + } } }, BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7ea472ed504a3..e27e322db8858 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -496,7 +496,8 @@ pub enum BuiltinLintDiagnostics { BreakWithLabelAndLoop(Span), NamedAsmLabel(String), UnicodeTextFlow(Span, String), - UnexpectedCfg((Symbol, Span), Option<(Symbol, Span)>), + UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), + UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), DeprecatedWhereclauseLocation(Span, String), SingleUseLifetime { /// Span of the parameter which declares this lifetime. diff --git a/tests/ui/check-cfg/diagnotics.rs b/tests/ui/check-cfg/diagnotics.rs new file mode 100644 index 0000000000000..49e127d079a79 --- /dev/null +++ b/tests/ui/check-cfg/diagnotics.rs @@ -0,0 +1,31 @@ +// check-pass +// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --check-cfg=values(no_values) -Z unstable-options + +#[cfg(featur)] +//~^ WARNING unexpected `cfg` condition name +fn feature() {} + +#[cfg(featur = "foo")] +//~^ WARNING unexpected `cfg` condition name +fn feature() {} + +#[cfg(featur = "fo")] +//~^ WARNING unexpected `cfg` condition name +fn feature() {} + +#[cfg(feature = "foo")] +fn feature() {} + +#[cfg(no_value)] +//~^ WARNING unexpected `cfg` condition name +fn no_values() {} + +#[cfg(no_value = "foo")] +//~^ WARNING unexpected `cfg` condition name +fn no_values() {} + +#[cfg(no_values = "bar")] +//~^ WARNING unexpected `cfg` condition value +fn no_values() {} + +fn main() {} diff --git a/tests/ui/check-cfg/diagnotics.stderr b/tests/ui/check-cfg/diagnotics.stderr new file mode 100644 index 0000000000000..8b9fef09d09ec --- /dev/null +++ b/tests/ui/check-cfg/diagnotics.stderr @@ -0,0 +1,62 @@ +warning: unexpected `cfg` condition name + --> $DIR/diagnotics.rs:4:7 + | +LL | #[cfg(featur)] + | ^^^^^^ help: there is a config with a similar name: `feature` + | + = help: expected values for `feature` are: `foo` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name + --> $DIR/diagnotics.rs:8:7 + | +LL | #[cfg(featur = "foo")] + | ^^^^^^^^^^^^^^ + | + = help: expected values for `feature` are: `foo` +help: there is a config with a similar name and value + | +LL | #[cfg(feature = "foo")] + | ~~~~~~~ + +warning: unexpected `cfg` condition name + --> $DIR/diagnotics.rs:12:7 + | +LL | #[cfg(featur = "fo")] + | ^^^^^^^^^^^^^ + | + = help: expected values for `feature` are: `foo` +help: there is a config with a similar name and different values + | +LL | #[cfg(feature = "foo")] + | ~~~~~~~~~~~~~~~ + +warning: unexpected `cfg` condition name + --> $DIR/diagnotics.rs:19:7 + | +LL | #[cfg(no_value)] + | ^^^^^^^^ help: there is a config with a similar name: `no_values` + +warning: unexpected `cfg` condition name + --> $DIR/diagnotics.rs:23:7 + | +LL | #[cfg(no_value = "foo")] + | ^^^^^^^^^^^^^^^^ + | +help: there is a config with a similar name and no value + | +LL | #[cfg(no_values)] + | ~~~~~~~~~ + +warning: unexpected `cfg` condition value + --> $DIR/diagnotics.rs:27:7 + | +LL | #[cfg(no_values = "bar")] + | ^^^^^^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `no_values` + +warning: 6 warnings emitted + diff --git a/tests/ui/check-cfg/invalid-cfg-name.stderr b/tests/ui/check-cfg/invalid-cfg-name.stderr index 01ee4f209f1e6..ed09f8cb66d29 100644 --- a/tests/ui/check-cfg/invalid-cfg-name.stderr +++ b/tests/ui/check-cfg/invalid-cfg-name.stderr @@ -2,7 +2,7 @@ warning: unexpected `cfg` condition name --> $DIR/invalid-cfg-name.rs:7:7 | LL | #[cfg(widnows)] - | ^^^^^^^ help: there is an config with a similar name: `windows` + | ^^^^^^^ help: there is a config with a similar name: `windows` | = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/invalid-cfg-value.stderr index 0ef8a06dc92e2..776d264a7adcb 100644 --- a/tests/ui/check-cfg/invalid-cfg-value.stderr +++ b/tests/ui/check-cfg/invalid-cfg-value.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- | | - | help: there is an expected value with a similar name: `"serde"` + | help: there is a expected value with a similar name: `"serde"` | = note: expected values for `feature` are: `full`, `serde` = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index 4e488fc03ec4b..9adf5c46e43fe 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -12,6 +12,10 @@ fn do_windows_stuff() {} //~^ WARNING unexpected `cfg` condition name fn do_windows_stuff() {} +#[cfg(feature)] +//~^ WARNING unexpected `cfg` condition value +fn no_feature() {} + #[cfg(feature = "foo")] fn use_foo() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index e3738af13ff5f..07c514aed5242 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -2,12 +2,20 @@ warning: unexpected `cfg` condition name --> $DIR/mix.rs:11:7 | LL | #[cfg(widnows)] - | ^^^^^^^ help: there is an config with a similar name: `windows` + | ^^^^^^^ help: there is a config with a similar name: `windows` | = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value - --> $DIR/mix.rs:18:7 + --> $DIR/mix.rs:15:7 + | +LL | #[cfg(feature)] + | ^^^^^^^- help: specify a config value: `= "foo"` + | + = note: expected values for `feature` are: `foo` + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:22:7 | LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ @@ -15,7 +23,7 @@ LL | #[cfg(feature = "bar")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value - --> $DIR/mix.rs:22:7 + --> $DIR/mix.rs:26:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ @@ -23,7 +31,7 @@ LL | #[cfg(feature = "zebra")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name - --> $DIR/mix.rs:26:12 + --> $DIR/mix.rs:30:12 | LL | #[cfg_attr(uu, test)] | ^^ @@ -37,13 +45,13 @@ warning: unexpected `unknown_name` as condition name = help: was set with `--cfg` but isn't in the `--check-cfg` expected names warning: unexpected `cfg` condition name - --> $DIR/mix.rs:35:10 + --> $DIR/mix.rs:39:10 | LL | cfg!(widnows); - | ^^^^^^^ help: there is an config with a similar name: `windows` + | ^^^^^^^ help: there is a config with a similar name: `windows` warning: unexpected `cfg` condition value - --> $DIR/mix.rs:38:10 + --> $DIR/mix.rs:42:10 | LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ @@ -51,7 +59,7 @@ LL | cfg!(feature = "bar"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value - --> $DIR/mix.rs:40:10 + --> $DIR/mix.rs:44:10 | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ @@ -59,25 +67,25 @@ LL | cfg!(feature = "zebra"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name - --> $DIR/mix.rs:42:10 + --> $DIR/mix.rs:46:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:44:10 + --> $DIR/mix.rs:48:10 | LL | cfg!(xxx); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:46:14 + --> $DIR/mix.rs:50:14 | LL | cfg!(any(xxx, windows)); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:48:14 + --> $DIR/mix.rs:52:14 | LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ @@ -85,43 +93,43 @@ LL | cfg!(any(feature = "bad", windows)); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name - --> $DIR/mix.rs:50:23 + --> $DIR/mix.rs:54:23 | LL | cfg!(any(windows, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:52:20 + --> $DIR/mix.rs:56:20 | LL | cfg!(all(unix, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:54:14 + --> $DIR/mix.rs:58:14 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:54:18 + --> $DIR/mix.rs:58:18 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:57:14 + --> $DIR/mix.rs:61:14 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:57:18 + --> $DIR/mix.rs:61:18 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:60:20 + --> $DIR/mix.rs:64:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -129,13 +137,13 @@ LL | cfg!(any(unix, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name - --> $DIR/mix.rs:62:14 + --> $DIR/mix.rs:66:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:62:19 + --> $DIR/mix.rs:66:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -143,19 +151,19 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name - --> $DIR/mix.rs:65:14 + --> $DIR/mix.rs:69:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition name - --> $DIR/mix.rs:65:25 + --> $DIR/mix.rs:69:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition value - --> $DIR/mix.rs:68:14 + --> $DIR/mix.rs:72:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -163,7 +171,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value - --> $DIR/mix.rs:68:33 + --> $DIR/mix.rs:72:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -171,12 +179,12 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value - --> $DIR/mix.rs:68:52 + --> $DIR/mix.rs:72:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `foo` -warning: 27 warnings emitted +warning: 28 warnings emitted diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr index 8500fc0880503..eb81535e3edb0 100644 --- a/tests/ui/check-cfg/values-target-json.stderr +++ b/tests/ui/check-cfg/values-target-json.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_os = "linuz")] | ^^^^^^^^^^^^------- | | - | help: there is an expected value with a similar name: `"linux"` + | help: there is a expected value with a similar name: `"linux"` | = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index 987339a222a12..34c5d6172d94d 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name LL | #[cfg(target_oz = "linux")] | ---------^^^^^^^^^^ | | - | help: there is an config with a similar name: `target_os` + | help: there is a config with a similar name: `target_os` | = note: `#[warn(unexpected_cfgs)]` on by default @@ -14,13 +14,13 @@ warning: unexpected `cfg` condition name LL | #[cfg(features = "foo")] | --------^^^^^^^^ | | - | help: there is an config with a similar name: `feature` + | help: there is a config with a similar name: `feature` warning: unexpected `cfg` condition name --> $DIR/well-known-names.rs:20:7 | LL | #[cfg(uniw)] - | ^^^^ help: there is an config with a similar name: `unix` + | ^^^^ help: there is a config with a similar name: `unix` warning: 3 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 4bd8e6ae09f29..2d18cb82e037a 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_os = "linuz")] | ^^^^^^^^^^^^------- | | - | help: there is an expected value with a similar name: `"linux"` + | help: there is a expected value with a similar name: `"linux"` | = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` = note: `#[warn(unexpected_cfgs)]` on by default @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(target_has_atomic = "0")] | ^^^^^^^^^^^^^^^^^^^^--- | | - | help: there is an expected value with a similar name: `"8"` + | help: there is a expected value with a similar name: `"8"` | = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`