From 1238a20d38d976ccd4ccecf1b9e2cab039ab6d63 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 31 Mar 2025 17:58:05 +0200 Subject: [PATCH 1/3] Expose `LintLevelsBuilder` with crate root builder --- compiler/rustc_lint/src/levels.rs | 13 +++++++++++++ compiler/rustc_lint/src/lib.rs | 1 + 2 files changed, 14 insertions(+) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 8718fb807ecf5..313d8f6ba8ff4 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -450,6 +450,19 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { builder } + pub fn crate_root( + sess: &'s Session, + features: &'s Features, + lint_added_lints: bool, + store: &'s LintStore, + registered_tools: &'s RegisteredTools, + crate_attrs: &[ast::Attribute], + ) -> Self { + let mut builder = Self::new(sess, features, lint_added_lints, store, registered_tools); + builder.add(crate_attrs, true, None); + builder + } + fn process_command_line(&mut self) { self.provider.cur = self .provider diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a754001811..0c875a4b1bc05 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -129,6 +129,7 @@ pub use context::{ }; pub use early::{EarlyCheckNode, check_ast_node}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; +pub use levels::LintLevelsBuilder; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{ From 69cb0a9e15393bf9dea483725a2cfdba74dff47d Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 31 Mar 2025 18:00:28 +0200 Subject: [PATCH 2/3] Expose `registered_tools` directly without `TyCtxt`-query --- compiler/rustc_resolve/src/lib.rs | 2 ++ compiler/rustc_resolve/src/macros.rs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 78153fd417407..6ef26d7d53a64 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -88,6 +88,8 @@ mod late; mod macros; pub mod rustdoc; +pub use macros::registered_tools_ast; + rustc_fluent_macro::fluent_messages! { "../messages.ftl" } #[derive(Debug)] diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 3637854f1204f..49156f2d856c5 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -10,7 +10,7 @@ use rustc_ast::{self as ast, Crate, NodeId, attr}; use rustc_ast_pretty::pprust; use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr}; use rustc_data_structures::intern::Interned; -use rustc_errors::{Applicability, StashKey}; +use rustc_errors::{Applicability, DiagCtxtHandle, StashKey}; use rustc_expand::base::{ DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind, }; @@ -124,14 +124,21 @@ fn fast_print_path(path: &ast::Path) -> Symbol { } pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { - let mut registered_tools = RegisteredTools::default(); let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow(); + registered_tools_ast(tcx.dcx(), pre_configured_attrs) +} + +pub fn registered_tools_ast( + dcx: DiagCtxtHandle<'_>, + pre_configured_attrs: &[ast::Attribute], +) -> RegisteredTools { + let mut registered_tools = RegisteredTools::default(); for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) { for meta_item_inner in attr.meta_item_list().unwrap_or_default() { match meta_item_inner.ident() { Some(ident) => { if let Some(old_ident) = registered_tools.replace(ident) { - tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered { + dcx.emit_err(errors::ToolWasAlreadyRegistered { span: ident.span, tool: ident, old_ident_span: old_ident.span, @@ -139,7 +146,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } } None => { - tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers { + dcx.emit_err(errors::ToolOnlyAcceptsIdentifiers { span: meta_item_inner.span(), tool: sym::register_tool, }); From df18de57a540cc9ae2309fd53e49c9a627f7d849 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Mar 2025 15:56:41 +0200 Subject: [PATCH 3/3] Add unstable `--print=crate-root-lint-levels` --- compiler/rustc_driver_impl/src/lib.rs | 28 +++++ compiler/rustc_session/src/config.rs | 3 + .../print-crate-root-lint-levels.md | 23 ++++ .../print-crate-root-lint-levels/lib.rs | 5 + .../print-crate-root-lint-levels/rmake.rs | 118 ++++++++++++++++++ tests/run-make/rustc-help/help-v.stdout | 2 +- tests/run-make/rustc-help/help.stdout | 2 +- .../print-without-arg.stderr | 2 +- tests/ui/invalid-compile-flags/print.stderr | 2 +- .../ui/print-request/print-lints-help.stderr | 2 +- tests/ui/print-request/stability.rs | 4 + 11 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md create mode 100644 tests/run-make/print-crate-root-lint-levels/lib.rs create mode 100644 tests/run-make/print-crate-root-lint-levels/rmake.rs diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 37755e7d61db1..f1dc4bb795e51 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, + ®istered_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 ed336cc559612..1b01efda2a9ea 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 0000000000000..0bad8b8ab96bd --- /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 0000000000000..dc846f8fd9514 --- /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 0000000000000..e373c91102dfa --- /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::::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::::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::::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 98e56735082d1..f19ca1e9f90ab 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 040555f1d04fe..f7d352966035b 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 aa8a2ae42db29..8abaee5056bab 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 f9cfb1616ce5a..e3374eb1e6e7e 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 0530d11f2e802..bc48b2fa73cc7 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 c3421224d7206..0ec0886e941e7 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