Skip to content

Improve check-cfg implementation #111068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 5, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -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,32 +582,32 @@ 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 name",
BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
"unexpected `cfg` condition value",
BuiltinLintDiagnostics::UnexpectedCfgValue(
(cfg.name, cfg.name_span),
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
),
);
}
}
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)),
),
);
}
None if sess.check_config.exhaustive_names => {
sess.buffer_lint_with_diagnostic(
UNEXPECTED_CFGS,
cfg.span,
lint_node_id,
"unexpected `cfg` condition name",
BuiltinLintDiagnostics::UnexpectedCfgName(
(cfg.name, cfg.name_span),
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
),
);
}
_ => { /* not unexpected */ }
}
sess.config.contains(&(cfg.name, cfg.value))
})
76 changes: 48 additions & 28 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
@@ -9,11 +9,12 @@ 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;
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<String>) -> FxHashSet<(String, Option<String
/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
pub fn parse_check_cfg(specs: Vec<String>) -> 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,76 +138,95 @@ pub fn parse_check_cfg(specs: Vec<String>) -> 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.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");
}
}
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
.values_valid
let expected_values = check_cfg
.expecteds
.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, _)) =
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"
);
}
}

continue 'specs;
if values.is_empty() {
expected_values.insert(None);
}
} else {
error!(
"`values()` first argument must be a simple identifier"
);
}
} else if args.is_empty() {
cfg.well_known_values = true;
continue 'specs;
check_cfg.exhaustive_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());
}
cfg
check_cfg
})
}

20 changes: 10 additions & 10 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -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 */ }
}
}
}
70 changes: 54 additions & 16 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
@@ -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,22 +769,52 @@ pub trait LintContext: Sized {
db.help(help);
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((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<Symbol> = names_valid.iter().map(|s| *s).collect();
BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => {
let possibilities: Vec<Symbol> = 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, "did you mean", 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::<Vec<_>>();
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(values) = &sess.parse_sess.check_config.values_valid.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 possibilities: Vec<Symbol> = values.iter().map(|&s| s).collect();
let mut have_none_possibility = false;
let possibilities: Vec<Symbol> = values.iter()
.inspect(|a| have_none_possibility |= a.is_none())
.copied()
.flatten()
.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
@@ -792,17 +823,24 @@ pub trait LintContext: Sized {
let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
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);
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 {
} else if have_none_possibility {
db.note(format!("no expected value for `{name}`"));
if name != sym::feature {
if let Some((_value, value_span)) = value {
db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", "", Applicability::MaybeIncorrect);
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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.
233 changes: 125 additions & 108 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
@@ -1056,37 +1056,76 @@ 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 name checking is performed
pub names_valid: Option<FxHashSet<T>>,
/// 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<T, FxHashSet<T>>,
pub exhaustive_values: bool,
/// All the expected values for a config name
pub expecteds: FxHashMap<T, ExpectedValues<T>>,
}

impl<T> Default for CheckCfg<T> {
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<T> CheckCfg<T> {
fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
fn map_data<O: Eq + Hash>(self, f: impl Fn(T) -> O) -> CheckCfg<O> {
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<T> {
Some(FxHashSet<Option<T>>),
Any,
}

impl<T: Eq + Hash> ExpectedValues<T> {
fn insert(&mut self, value: T) -> bool {
match self {
ExpectedValues::Some(expecteds) => expecteds.insert(Some(value)),
ExpectedValues::Any => false,
}
}
}

impl<T: Eq + Hash> Extend<T> for ExpectedValues<T> {
fn extend<I: IntoIterator<Item = T>>(&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<T> {
fn extend<I: IntoIterator<Item = &'a T>>(&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<T> CheckCfg<T> {
/// `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 {
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/check-cfg/check-cfg.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion tests/rustdoc-ui/doctest/check-cfg-test.stderr
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/compact-values.stderr
Original file line number Diff line number Diff line change
@@ -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
31 changes: 31 additions & 0 deletions tests/ui/check-cfg/diagnotics.rs
Original file line number Diff line number Diff line change
@@ -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() {}
62 changes: 62 additions & 0 deletions tests/ui/check-cfg/diagnotics.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion tests/ui/check-cfg/invalid-cfg-name.stderr
Original file line number Diff line number Diff line change
@@ -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 a config with a similar name: `windows`
|
= note: `#[warn(unexpected_cfgs)]` on by default

6 changes: 3 additions & 3 deletions tests/ui/check-cfg/invalid-cfg-value.stderr
Original file line number Diff line number Diff line change
@@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value
LL | #[cfg(feature = "sedre")]
| ^^^^^^^^^^-------
| |
| help: did you mean: `"serde"`
| help: there is a 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`
|
4 changes: 4 additions & 0 deletions tests/ui/check-cfg/mix.rs
Original file line number Diff line number Diff line change
@@ -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() {}

82 changes: 45 additions & 37 deletions tests/ui/check-cfg/mix.stderr
Original file line number Diff line number Diff line change
@@ -2,28 +2,36 @@ warning: unexpected `cfg` condition name
--> $DIR/mix.rs:11:7
|
LL | #[cfg(widnows)]
| ^^^^^^^ help: did you mean: `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")]
| ^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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")]
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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,146 +45,146 @@ 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: did you mean: `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");
| ^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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");
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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));
| ^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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"));
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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"));
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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"));
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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"));
| ^^^^^^^^^^^^^^^^^
|
= note: expected values for `feature` are: foo
= 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
= note: expected values for `feature` are: `foo`

warning: 27 warnings emitted
warning: 28 warnings emitted

4 changes: 3 additions & 1 deletion tests/ui/check-cfg/no-values.stderr
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions tests/ui/check-cfg/values-target-json.stderr
Original file line number Diff line number Diff line change
@@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value
LL | #[cfg(target_os = "linuz")]
| ^^^^^^^^^^^^-------
| |
| help: did you mean: `"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: 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
6 changes: 3 additions & 3 deletions tests/ui/check-cfg/well-known-names.stderr
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name
LL | #[cfg(target_oz = "linux")]
| ---------^^^^^^^^^^
| |
| help: did you mean: `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: did you mean: `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: did you mean: `unix`
| ^^^^ help: there is a config with a similar name: `unix`

warning: 3 warnings emitted

8 changes: 4 additions & 4 deletions tests/ui/check-cfg/well-known-values.stderr
Original file line number Diff line number Diff line change
@@ -4,9 +4,9 @@ warning: unexpected `cfg` condition value
LL | #[cfg(target_os = "linuz")]
| ^^^^^^^^^^^^-------
| |
| help: did you mean: `"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: 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 a 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