about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-05-29 03:25:07 +0100
committerGitHub <noreply@github.com>2024-05-29 03:25:07 +0100
commit7e441a11a151098a0ff928fdeb52492798678ede (patch)
tree749ba591bfb7ee5f358bb0a9f026581591d7b887
parent2d3b1e014be923767f36c4b231feb2672e853043 (diff)
parentac59bdc20cf07422557b5dc512ee6749a73c9414 (diff)
downloadrust-7e441a11a151098a0ff928fdeb52492798678ede.tar.gz
rust-7e441a11a151098a0ff928fdeb52492798678ede.zip
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``
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs33
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--src/doc/unstable-book/src/compiler-flags/print-check-cfg.md25
-rw-r--r--tests/run-make/print-check-cfg/lib.rs1
-rw-r--r--tests/run-make/print-check-cfg/rmake.rs106
-rw-r--r--tests/ui/feature-gates/feature-gate-print-check-cfg.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-print-check-cfg.stderr2
-rw-r--r--tests/ui/invalid-compile-flags/print.stderr2
8 files changed, 184 insertions, 2 deletions
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2bd58680eef..08b97b4953e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -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();
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c90da966e70..0287085ad60 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -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 =
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
new file mode 100644
index 00000000000..e55165b5374
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md
@@ -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
+```
diff --git a/tests/run-make/print-check-cfg/lib.rs b/tests/run-make/print-check-cfg/lib.rs
new file mode 100644
index 00000000000..c09e4c98dff
--- /dev/null
+++ b/tests/run-make/print-check-cfg/lib.rs
@@ -0,0 +1 @@
+// empty crate
diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs
new file mode 100644
index 00000000000..554884b7d57
--- /dev/null
+++ b/tests/run-make/print-check-cfg/rmake.rs
@@ -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);
+}
diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs
new file mode 100644
index 00000000000..304e0c132e5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs
@@ -0,0 +1,3 @@
+//@ compile-flags: --print=check-cfg
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr
new file mode 100644
index 00000000000..62ee44b94a4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the check-cfg print option
+
diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr
index 0a032aabdfe..70b4a394dd0 100644
--- a/tests/ui/invalid-compile-flags/print.stderr
+++ b/tests/ui/invalid-compile-flags/print.stderr
@@ -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`