Skip to content
Merged
Show file tree
Hide file tree
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
35 changes: 20 additions & 15 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}");
Expand Down
29 changes: 17 additions & 12 deletions src/doc/unstable-book/src/compiler-flags/print-check-cfg.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,28 @@ 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:

```bash
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
18 changes: 17 additions & 1 deletion src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,11 +1065,27 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
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"];

Expand Down
66 changes: 36 additions & 30 deletions tests/run-make/print-check-cfg/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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)"],
},
});
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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());
}
}
}
Loading