Rollup merge of #124320 - Urgau:print-check-cfg, r=petrochenkov

Add `--print=check-cfg` to get the expected configs

This PR adds a new `--print` variant `check-cfg` to get the expected configs.

Details and rational can be found on the MCP: https://github.com/rust-lang/compiler-team/issues/743

``@rustbot`` label +F-check-cfg +S-waiting-on-MCP
r? ``@petrochenkov``
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-05-29 03:25:07 +01:00 committed by GitHub
commit 7e441a11a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 184 additions and 2 deletions

View File

@ -804,6 +804,39 @@ fn print_crate_info(
println_info!("{cfg}");
}
}
CheckCfg => {
let mut check_cfgs: Vec<String> = Vec::with_capacity(410);
// INSTABILITY: We are sorting the output below.
#[allow(rustc::potential_query_instability)]
for (name, expected_values) in &sess.psess.check_config.expecteds {
use crate::config::ExpectedValues;
match expected_values {
ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")),
ExpectedValues::Some(values) => {
check_cfgs.extend(values.iter().map(|value| {
if let Some(value) = value {
format!("{name}=\"{value}\"")
} else {
name.to_string()
}
}))
}
}
}
check_cfgs.sort_unstable();
if !sess.psess.check_config.exhaustive_names {
if !sess.psess.check_config.exhaustive_values {
println_info!("any()=any()");
} else {
println_info!("any()");
}
}
for check_cfg in check_cfgs {
println_info!("{check_cfg}");
}
}
CallingConventions => {
let mut calling_conventions = rustc_target::spec::abi::all_names();
calling_conventions.sort_unstable();

View File

@ -773,6 +773,7 @@ pub enum PrintKind {
TargetLibdir,
CrateName,
Cfg,
CheckCfg,
CallingConventions,
TargetList,
TargetCPUs,
@ -1443,7 +1444,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"",
"print",
"Compiler information to print on stdout",
"[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\
"[crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|\
target-list|target-cpus|target-features|relocation-models|code-models|\
tls-models|target-spec-json|all-target-specs-json|native-static-libs|\
stack-protector-strategies|link-args|deployment-target]",
@ -1859,6 +1860,7 @@ fn collect_print_requests(
("all-target-specs-json", PrintKind::AllTargetSpecs),
("calling-conventions", PrintKind::CallingConventions),
("cfg", PrintKind::Cfg),
("check-cfg", PrintKind::CheckCfg),
("code-models", PrintKind::CodeModels),
("crate-name", PrintKind::CrateName),
("deployment-target", PrintKind::DeploymentTarget),
@ -1908,6 +1910,16 @@ fn collect_print_requests(
);
}
}
Some((_, PrintKind::CheckCfg)) => {
if unstable_opts.unstable_options {
PrintKind::CheckCfg
} else {
early_dcx.early_fatal(
"the `-Z unstable-options` flag must also be passed to \
enable the check-cfg print option",
);
}
}
Some(&(_, print_kind)) => print_kind,
None => {
let prints =

View File

@ -0,0 +1,25 @@
# `print=check-cfg`
The tracking issue for this feature is: [#XXXXXX](https://github.com/rust-lang/rust/issues/XXXXXX).
------------------------
This option of the `--print` flag print the list of expected cfgs.
This is related to the `--check-cfg` flag which allows specifying arbitrary expected
names and values.
This print option works similarly to `--print=cfg` (modulo check-cfg specifics):
- *check_cfg syntax*: *output of --print=check-cfg*
- `cfg(windows)`: `windows`
- `cfg(feature, values("foo", "bar"))`: `feature="foo"` and `feature="bar"`
- `cfg(feature, values(none(), ""))`: `feature` and `feature=""`
- `cfg(feature, values(any()))`: `feature=any()`
- `cfg(any())`: `any()`
- *nothing*: `any()=any()`
To be used like this:
```bash
rustc --print=check-cfg -Zunstable-options lib.rs
```

View File

@ -0,0 +1 @@
// empty crate

View File

@ -0,0 +1,106 @@
//! This checks the output of `--print=check-cfg`
extern crate run_make_support;
use std::collections::HashSet;
use std::iter::FromIterator;
use std::ops::Deref;
use run_make_support::rustc;
fn main() {
check(
/*args*/ &[],
/*has_any*/ false,
/*has_any_any*/ true,
/*contains*/ &[],
);
check(
/*args*/ &["--check-cfg=cfg()"],
/*has_any*/ false,
/*has_any_any*/ false,
/*contains*/ &["unix", "miri"],
);
check(
/*args*/ &["--check-cfg=cfg(any())"],
/*has_any*/ true,
/*has_any_any*/ false,
/*contains*/ &["windows", "test"],
);
check(
/*args*/ &["--check-cfg=cfg(feature)"],
/*has_any*/ false,
/*has_any_any*/ false,
/*contains*/ &["unix", "miri", "feature"],
);
check(
/*args*/ &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#],
/*has_any*/ false,
/*has_any_any*/ false,
/*contains*/ &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""],
);
check(
/*args*/ &[
r#"--check-cfg=cfg(feature, values(any()))"#,
r#"--check-cfg=cfg(feature, values("tmp"))"#
],
/*has_any*/ false,
/*has_any_any*/ false,
/*contains*/ &["unix", "miri", "feature=any()"],
);
check(
/*args*/ &[
r#"--check-cfg=cfg(has_foo, has_bar)"#,
r#"--check-cfg=cfg(feature, values("tmp"))"#,
r#"--check-cfg=cfg(feature, values("tmp"))"#
],
/*has_any*/ false,
/*has_any_any*/ false,
/*contains*/ &["has_foo", "has_bar", "feature=\"tmp\""],
);
}
fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) {
let output = rustc()
.input("lib.rs")
.arg("-Zunstable-options")
.arg("--print=check-cfg")
.args(&*args)
.run();
let stdout = String::from_utf8(output.stdout).unwrap();
let mut found_any = false;
let mut found_any_any = false;
let mut found = HashSet::<String>::new();
let mut recorded = HashSet::<String>::new();
for l in stdout.lines() {
assert!(l == l.trim());
if l == "any()" {
found_any = true;
} else if l == "any()=any()" {
found_any_any = true;
} else if let Some((left, right)) = l.split_once('=') {
if right != "any()" && right != "" {
assert!(right.starts_with("\""));
assert!(right.ends_with("\""));
}
assert!(!left.contains("\""));
} else {
assert!(!l.contains("\""));
}
assert!(recorded.insert(l.to_string()), "{}", &l);
if contains.contains(&l) {
assert!(found.insert(l.to_string()), "{}", &l);
}
}
let should_found = HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
let diff: Vec<_> = should_found.difference(&found).collect();
assert_eq!(found_any, has_any);
assert_eq!(found_any_any, has_any_any);
assert_eq!(found_any_any, recorded.len() == 1);
assert!(diff.is_empty(), "{:?} != {:?} (~ {:?})", &should_found, &found, &diff);
}

View File

@ -0,0 +1,3 @@
//@ compile-flags: --print=check-cfg
fn main() {}

View File

@ -0,0 +1,2 @@
error: the `-Z unstable-options` flag must also be passed to enable the check-cfg print option

View File

@ -1,4 +1,4 @@
error: unknown print request: `yyyy`
|
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`