about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2025-03-30 15:56:41 +0200
committerUrgau <urgau@numericable.fr>2025-04-01 18:29:39 +0200
commitdf18de57a540cc9ae2309fd53e49c9a627f7d849 (patch)
treef3f9dbe6dc7acde95211abd9518f7fbd954e9162
parent69cb0a9e15393bf9dea483725a2cfdba74dff47d (diff)
downloadrust-df18de57a540cc9ae2309fd53e49c9a627f7d849.tar.gz
rust-df18de57a540cc9ae2309fd53e49c9a627f7d849.zip
Add unstable `--print=crate-root-lint-levels`
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs28
-rw-r--r--compiler/rustc_session/src/config.rs3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md23
-rw-r--r--tests/run-make/print-crate-root-lint-levels/lib.rs5
-rw-r--r--tests/run-make/print-crate-root-lint-levels/rmake.rs118
-rw-r--r--tests/run-make/rustc-help/help-v.stdout2
-rw-r--r--tests/run-make/rustc-help/help.stdout2
-rw-r--r--tests/ui/invalid-compile-flags/print-without-arg.stderr2
-rw-r--r--tests/ui/invalid-compile-flags/print.stderr2
-rw-r--r--tests/ui/print-request/print-lints-help.stderr2
-rw-r--r--tests/ui/print-request/stability.rs4
11 files changed, 186 insertions, 5 deletions
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 37755e7d61d..f1dc4bb795e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -691,6 +691,34 @@ fn print_crate_info(
                 };
                 println_info!("{}", passes::get_crate_name(sess, attrs));
             }
+            CrateRootLintLevels => {
+                let Some(attrs) = attrs.as_ref() else {
+                    // no crate attributes, print out an error and exit
+                    return Compilation::Continue;
+                };
+                let crate_name = passes::get_crate_name(sess, attrs);
+                let lint_store = crate::unerased_lint_store(sess);
+                let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs);
+                let features = rustc_expand::config::features(sess, attrs, crate_name);
+                let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(
+                    sess,
+                    &features,
+                    true,
+                    lint_store,
+                    &registered_tools,
+                    attrs,
+                );
+                for lint in lint_store.get_lints() {
+                    if let Some(feature_symbol) = lint.feature_gate
+                        && !features.enabled(feature_symbol)
+                    {
+                        // lint is unstable and feature gate isn't active, don't print
+                        continue;
+                    }
+                    let level = lint_levels.lint_level(lint).0;
+                    println_info!("{}={}", lint.name_lower(), level.as_str());
+                }
+            }
             Cfg => {
                 let mut cfgs = sess
                     .psess
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index ed336cc5596..1b01efda2a9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -50,6 +50,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("check-cfg", PrintKind::CheckCfg),
     ("code-models", PrintKind::CodeModels),
     ("crate-name", PrintKind::CrateName),
+    ("crate-root-lint-levels", PrintKind::CrateRootLintLevels),
     ("deployment-target", PrintKind::DeploymentTarget),
     ("file-names", PrintKind::FileNames),
     ("host-tuple", PrintKind::HostTuple),
@@ -881,6 +882,7 @@ pub enum PrintKind {
     CheckCfg,
     CodeModels,
     CrateName,
+    CrateRootLintLevels,
     DeploymentTarget,
     FileNames,
     HostTuple,
@@ -2067,6 +2069,7 @@ fn check_print_request_stability(
     match print_kind {
         PrintKind::AllTargetSpecsJson
         | PrintKind::CheckCfg
+        | PrintKind::CrateRootLintLevels
         | PrintKind::SupportedCrateTypes
         | PrintKind::TargetSpecJson
             if !unstable_opts.unstable_options =>
diff --git a/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md
new file mode 100644
index 00000000000..0bad8b8ab96
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md
@@ -0,0 +1,23 @@
+# `print=crate-root-lint-levels`
+
+The tracking issue for this feature is: [#139180](https://github.com/rust-lang/rust/issues/139180).
+
+------------------------
+
+This option of the `--print` flag print the list of lints with print out all the lints and their associated levels (`allow`, `warn`, `deny`, `forbid`) based on the regular Rust rules at crate root, that is *(roughly)*:
+ - command line args (`-W`, `-A`, `--force-warn`, `--cap-lints`, ...)
+ - crate root attributes (`#![allow]`, `#![warn]`, `#[expect]`, ...)
+ - *the special `warnings` lint group*
+ - the default lint level
+
+The output format is `LINT_NAME=LINT_LEVEL`, e.g.:
+```text
+unknown_lint=warn
+arithmetic_overflow=deny
+```
+
+To be used like this:
+
+```bash
+rustc --print=crate-root-lint-levels -Zunstable-options lib.rs
+```
diff --git a/tests/run-make/print-crate-root-lint-levels/lib.rs b/tests/run-make/print-crate-root-lint-levels/lib.rs
new file mode 100644
index 00000000000..dc846f8fd95
--- /dev/null
+++ b/tests/run-make/print-crate-root-lint-levels/lib.rs
@@ -0,0 +1,5 @@
+#![allow(unexpected_cfgs)]
+#![expect(unused_mut)]
+
+#[deny(unknown_lints)]
+mod my_mod {}
diff --git a/tests/run-make/print-crate-root-lint-levels/rmake.rs b/tests/run-make/print-crate-root-lint-levels/rmake.rs
new file mode 100644
index 00000000000..e373c91102d
--- /dev/null
+++ b/tests/run-make/print-crate-root-lint-levels/rmake.rs
@@ -0,0 +1,118 @@
+//! This checks the output of `--print=crate-root-lint-levels`
+
+extern crate run_make_support;
+
+use std::collections::HashSet;
+use std::iter::FromIterator;
+
+use run_make_support::rustc;
+
+struct CrateRootLintLevels {
+    args: &'static [&'static str],
+    contains: Contains,
+}
+
+struct Contains {
+    contains: &'static [&'static str],
+    doesnt_contain: &'static [&'static str],
+}
+
+fn main() {
+    check(CrateRootLintLevels {
+        args: &[],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "unused_mut=expect",
+                "warnings=warn",
+                "stable_features=warn",
+                "unknown_lints=warn",
+            ],
+            doesnt_contain: &["unexpected_cfgs=warn", "unused_mut=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Wunexpected_cfgs"],
+        contains: Contains {
+            contains: &["unexpected_cfgs=allow", "warnings=warn"],
+            doesnt_contain: &["unexpected_cfgs=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings"],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "warnings=deny",
+                "stable_features=deny",
+                "unknown_lints=deny",
+            ],
+            doesnt_contain: &["warnings=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dstable_features"],
+        contains: Contains {
+            contains: &["warnings=warn", "stable_features=deny", "unexpected_cfgs=allow"],
+            doesnt_contain: &["warnings=deny"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings", "--force-warn=stable_features"],
+        contains: Contains {
+            contains: &["warnings=deny", "stable_features=force-warn", "unknown_lints=deny"],
+            doesnt_contain: &["warnings=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings", "--cap-lints=warn"],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "warnings=warn",
+                "stable_features=warn",
+                "unknown_lints=warn",
+            ],
+            doesnt_contain: &["warnings=deny"],
+        },
+    });
+}
+
+#[track_caller]
+fn check(CrateRootLintLevels { args, contains }: CrateRootLintLevels) {
+    let output = rustc()
+        .input("lib.rs")
+        .arg("-Zunstable-options")
+        .print("crate-root-lint-levels")
+        .args(args)
+        .run();
+
+    let stdout = output.stdout_utf8();
+
+    let mut found = HashSet::<String>::new();
+
+    for l in stdout.lines() {
+        assert!(l == l.trim());
+        if let Some((left, right)) = l.split_once('=') {
+            assert!(!left.contains("\""));
+            assert!(!right.contains("\""));
+        } else {
+            assert!(l.contains('='));
+        }
+        assert!(found.insert(l.to_string()), "{}", &l);
+    }
+
+    let Contains { contains, doesnt_contain } = contains;
+
+    {
+        let should_found = HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
+        let diff: Vec<_> = should_found.difference(&found).collect();
+        assert!(diff.is_empty(), "should found: {:?}, didn't found {:?}", &should_found, &diff);
+    }
+    {
+        let should_not_find =
+            HashSet::<String>::from_iter(doesnt_contain.iter().map(|s| s.to_string()));
+        let diff: Vec<_> = should_not_find.intersection(&found).collect();
+        assert!(diff.is_empty(), "should not find {:?}, did found {:?}", &should_not_find, &diff);
+    }
+}
diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout
index 98e56735082..f19ca1e9f90 100644
--- a/tests/run-make/rustc-help/help-v.stdout
+++ b/tests/run-make/rustc-help/help-v.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout
index 040555f1d04..f7d35296603 100644
--- a/tests/run-make/rustc-help/help.stdout
+++ b/tests/run-make/rustc-help/help.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr
index aa8a2ae42db..8abaee5056b 100644
--- a/tests/ui/invalid-compile-flags/print-without-arg.stderr
+++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr
@@ -1,5 +1,5 @@
 error: Argument to option 'print' missing
        Usage:
-           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                                Compiler information to print on stdout
 
diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr
index f9cfb1616ce..e3374eb1e6e 100644
--- a/tests/ui/invalid-compile-flags/print.stderr
+++ b/tests/ui/invalid-compile-flags/print.stderr
@@ -1,5 +1,5 @@
 error: unknown print request: `yyyy`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `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`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 
diff --git a/tests/ui/print-request/print-lints-help.stderr b/tests/ui/print-request/print-lints-help.stderr
index 0530d11f2e8..bc48b2fa73c 100644
--- a/tests/ui/print-request/print-lints-help.stderr
+++ b/tests/ui/print-request/print-lints-help.stderr
@@ -1,6 +1,6 @@
 error: unknown print request: `lints`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `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`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: use `-Whelp` to print a list of lints
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 
diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs
index c3421224d72..0ec0886e941 100644
--- a/tests/ui/print-request/stability.rs
+++ b/tests/ui/print-request/stability.rs
@@ -18,6 +18,10 @@
 //@[all_target_specs_json] compile-flags: --print=all-target-specs-json
 //@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed
 
+//@ revisions: crate_root_lint_levels
+//@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels
+//@[crate_root_lint_levels] error-pattern: the `-Z unstable-options` flag must also be passed
+
 //@ revisions: check_cfg
 //@[check_cfg] compile-flags: --print=check-cfg
 //@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed