diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7820198f2dcf2..a328298d3b153 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -765,30 +765,35 @@ fn print_crate_info( 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::Any => { + check_cfgs.push(format!("cfg({name}, values(any()))")) + } ExpectedValues::Some(values) => { - if !values.is_empty() { - check_cfgs.extend(values.iter().map(|value| { + let mut values: Vec<_> = values + .iter() + .map(|value| { if let Some(value) = value { - format!("{name}=\"{value}\"") + format!("\"{value}\"") } else { - name.to_string() + "none()".to_string() } - })) - } else { - check_cfgs.push(format!("{name}=")) - } + }) + .collect(); + + values.sort_unstable(); + + let values = values.join(", "); + + check_cfgs.push(format!("cfg({name}, values({values}))")) } } } 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()"); - } + if !sess.psess.check_config.exhaustive_names + && sess.psess.check_config.exhaustive_values + { + println_info!("cfg(any())"); } for check_cfg in check_cfgs { println_info!("{check_cfg}"); diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md index 8d314aa62d4cc..1b41a0cd728fc 100644 --- a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md @@ -9,18 +9,20 @@ This option of the `--print` flag print the list of all the expected cfgs. This is related to the [`--check-cfg` flag][check-cfg] which allows specifying arbitrary expected names and values. -This print option works similarly to `--print=cfg` (modulo check-cfg specifics). - -| `--check-cfg` | `--print=check-cfg` | -|-----------------------------------|-----------------------------| -| `cfg(foo)` | `foo` | -| `cfg(foo, values("bar"))` | `foo="bar"` | -| `cfg(foo, values(none(), "bar"))` | `foo` & `foo="bar"` | -| | *check-cfg specific syntax* | -| `cfg(foo, values(any())` | `foo=any()` | -| `cfg(foo, values())` | `foo=` | -| `cfg(any())` | `any()` | -| *none* | `any()=any()` | +This print option outputs compatible `--check-cfg` arguments with a reduced syntax where all the +expected values are on the same line and `values(...)` is always explicit. + +| `--check-cfg` | `--print=check-cfg` | +|-----------------------------------|-----------------------------------| +| `cfg(foo)` | `cfg(foo, values(none())) | +| `cfg(foo, values("bar"))` | `cfg(foo, values("bar"))` | +| `cfg(foo, values(none(), "bar"))` | `cfg(foo, values(none(), "bar"))` | +| `cfg(foo, values(any())` | `cfg(foo, values(any())` | +| `cfg(foo, values())` | `cfg(foo, values())` | +| `cfg(any())` | `cfg(any())` | +| *nothing* | *nothing* | + +The print option includes well known cfgs. To be used like this: @@ -28,4 +30,7 @@ To be used like this: rustc --print=check-cfg -Zunstable-options lib.rs ``` +> **Note:** Users should be resilient when parsing, in particular against new predicates that +may be added in the future. + [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 450fde3bbc38e..d2abc9dab1488 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1065,11 +1065,27 @@ fn builtin_cfg_names(config: &Config) -> HashSet { Default::default(), ) .lines() - .map(|l| if let Some((name, _)) = l.split_once('=') { name.to_string() } else { l.to_string() }) + .map(|l| extract_cfg_name(&l).unwrap().to_string()) .chain(std::iter::once(String::from("test"))) .collect() } +/// Extract the cfg name from `cfg(name, values(...))` lines +fn extract_cfg_name(check_cfg_line: &str) -> Result<&str, &'static str> { + let trimmed = check_cfg_line.trim(); + + #[rustfmt::skip] + let inner = trimmed + .strip_prefix("cfg(") + .ok_or("missing cfg(")? + .strip_suffix(")") + .ok_or("missing )")?; + + let first_comma = inner.find(',').ok_or("no comma found")?; + + Ok(inner[..first_comma].trim()) +} + pub const KNOWN_CRATE_TYPES: &[&str] = &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]; diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index f6f7f7cece6e7..e102d2904a80f 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -14,51 +14,55 @@ struct CheckCfg { enum Contains { Some { contains: &'static [&'static str], doesnt_contain: &'static [&'static str] }, - Only(&'static str), + Nothing, } fn main() { - check(CheckCfg { args: &[], contains: Contains::Only("any()=any()") }); + check(CheckCfg { args: &[], contains: Contains::Nothing }); check(CheckCfg { args: &["--check-cfg=cfg()"], contains: Contains::Some { - contains: &["unix", "miri"], - doesnt_contain: &["any()", "any()=any()"], + contains: &["cfg(unix, values(none()))", "cfg(miri, values(none()))"], + doesnt_contain: &["cfg(any())"], }, }); check(CheckCfg { args: &["--check-cfg=cfg(any())"], contains: Contains::Some { - contains: &["any()", "unix", r#"target_feature="crt-static""#], + contains: &["cfg(any())", "cfg(unix, values(none()))"], doesnt_contain: &["any()=any()"], }, }); check(CheckCfg { args: &["--check-cfg=cfg(feature)"], contains: Contains::Some { - contains: &["unix", "miri", "feature"], - doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + contains: &[ + "cfg(unix, values(none()))", + "cfg(miri, values(none()))", + "cfg(feature, values(none()))", + ], + doesnt_contain: &["cfg(any())", "cfg(feature)"], }, }); check(CheckCfg { args: &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#], contains: Contains::Some { - contains: &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""], - doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + contains: &[r#"cfg(feature, values("", "lol", "test", none()))"#], + doesnt_contain: &["cfg(any())", "cfg(feature, values(none()))", "cfg(feature)"], }, }); check(CheckCfg { args: &["--check-cfg=cfg(feature, values())"], contains: Contains::Some { - contains: &["feature="], - doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature"], + contains: &["cfg(feature, values())"], + doesnt_contain: &["cfg(any())", "cfg(feature, values(none()))", "cfg(feature)"], }, }); check(CheckCfg { args: &["--check-cfg=cfg(feature, values())", "--check-cfg=cfg(feature, values(none()))"], contains: Contains::Some { - contains: &["feature"], - doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + contains: &["cfg(feature, values(none()))"], + doesnt_contain: &["cfg(any())", "cfg(feature, values())"], }, }); check(CheckCfg { @@ -67,8 +71,8 @@ fn main() { r#"--check-cfg=cfg(feature, values("tmp"))"#, ], contains: Contains::Some { - contains: &["unix", "miri", "feature=any()"], - doesnt_contain: &["any()", "any()=any()", "feature", "feature=", "feature=\"tmp\""], + contains: &["cfg(feature, values(any()))"], + doesnt_contain: &["cfg(any())", r#"cfg(feature, values("tmp"))"#], }, }); check(CheckCfg { @@ -78,8 +82,12 @@ fn main() { r#"--check-cfg=cfg(feature, values("tmp"))"#, ], contains: Contains::Some { - contains: &["has_foo", "has_bar", "feature=\"tmp\""], - doesnt_contain: &["any()", "any()=any()", "feature"], + contains: &[ + "cfg(has_foo, values(none()))", + "cfg(has_bar, values(none()))", + r#"cfg(feature, values("tmp"))"#, + ], + doesnt_contain: &["cfg(any())", "cfg(feature)"], }, }); } @@ -94,16 +102,15 @@ fn check(CheckCfg { args, contains }: CheckCfg) { for l in stdout.lines() { assert!(l == l.trim()); - 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!(found.insert(l.to_string()), "{}", &l); + assert!(l.starts_with("cfg("), "{l}"); + assert!(l.ends_with(")"), "{l}"); + assert_eq!( + l.chars().filter(|c| *c == '(').count(), + l.chars().filter(|c| *c == ')').count(), + "{l}" + ); + assert!(l.chars().filter(|c| *c == '"').count() % 2 == 0, "{l}"); + assert!(found.insert(l.to_string()), "{l}"); } match contains { @@ -131,9 +138,8 @@ fn check(CheckCfg { args, contains }: CheckCfg) { ); } } - Contains::Only(only) => { - assert!(found.contains(&only.to_string()), "{:?} != {:?}", &only, &found); - assert!(found.len() == 1, "len: {}, instead of 1", found.len()); + Contains::Nothing => { + assert!(found.len() == 0, "len: {}, instead of 0", found.len()); } } }