diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 24d1cc8af82f5..a3280fb6885af 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -490,7 +490,7 @@ pub static TRACK_DIAGNOSTICS: AtomicRef (Option, LintLevelSource), + probe_for_lint_level: impl Fn(LintId) -> (Option, LintLevelSource), ) -> Level { // If `level` is none then we actually assume the default level for this lint. let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); @@ -90,8 +90,20 @@ pub fn reveal_actual_level( // future compatibility warning. if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { - if configured_warning_level != Level::Warn { + if let Some(configured_warning_level) = warnings_level + && configured_warning_level != Level::Warn + { + if matches!(warnings_src, LintLevelSource::CommandLine(..)) + && lint != LintId::of(builtin::WARNINGS) + && let (Some(lint_level), lint_src) = probe_for_lint_level(lint) + && matches!(lint_src, LintLevelSource::CommandLine(..)) + { + // We have a command-line `-Awarnings` *and* a command-line e.g. `-Wspecific-lint`. + // Let's have the `specific-lint`'s command-line level override the command-line + // `warnings` level. + level = lint_level; + *src = lint_src; + } else { level = configured_warning_level; *src = warnings_src; } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5be122ffbdeb0..fea8a00fad316 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1393,16 +1393,8 @@ pub fn build_session( target_override: Option, cfg_version: &'static str, ) -> Session { - // FIXME: This is not general enough to make the warning lint completely override - // normal diagnostic warnings, since the warning lint can also be denied and changed - // later via the source code. - let warnings_allow = sopts - .lint_opts - .iter() - .rfind(|&(key, _)| *key == "warnings") - .is_some_and(|&(_, level)| level == lint::Allow); let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow); - let can_emit_warnings = !(warnings_allow || cap_lints_allow); + let can_emit_warnings = !cap_lints_allow; let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), diff --git a/tests/ui/lint/command-line-allow-warnings.rs b/tests/ui/lint/command-line-allow-warnings.rs new file mode 100644 index 0000000000000..f1b6d195ae38e --- /dev/null +++ b/tests/ui/lint/command-line-allow-warnings.rs @@ -0,0 +1,27 @@ +// compile-flags: -A warnings + +fn main() { + // This will be overriden by the `-A warnings` command line option. + #[warn(non_snake_case)] + let _OwO = 0u8; + + // But this should not. + #[deny(non_snake_case)] + let _UwU = 0u8; + //~^ ERROR variable `_UwU` should have a snake case name + + bar(); + baz(); +} + +#[warn(warnings)] +fn bar() { + let _OwO = 0u8; + //~^ WARN variable `_OwO` should have a snake case name +} + +#[deny(warnings)] +fn baz() { + let _OwO = 0u8; + //~^ ERROR variable `_OwO` should have a snake case name +} diff --git a/tests/ui/lint/command-line-allow-warnings.stderr b/tests/ui/lint/command-line-allow-warnings.stderr new file mode 100644 index 0000000000000..2a840a8b887f0 --- /dev/null +++ b/tests/ui/lint/command-line-allow-warnings.stderr @@ -0,0 +1,35 @@ +error: variable `_UwU` should have a snake case name + --> $DIR/command-line-allow-warnings.rs:10:9 + | +LL | let _UwU = 0u8; + | ^^^^ help: convert the identifier to snake case: `_uw_u` + | +note: the lint level is defined here + --> $DIR/command-line-allow-warnings.rs:9:12 + | +LL | #[deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +warning: variable `_OwO` should have a snake case name + --> $DIR/command-line-allow-warnings.rs:19:9 + | +LL | let _OwO = 0u8; + | ^^^^ help: convert the identifier to snake case: `_ow_o` + | + = note: `#[warn(non_snake_case)]` on by default + +error: variable `_OwO` should have a snake case name + --> $DIR/command-line-allow-warnings.rs:25:9 + | +LL | let _OwO = 0u8; + | ^^^^ help: convert the identifier to snake case: `_ow_o` + | +note: the lint level is defined here + --> $DIR/command-line-allow-warnings.rs:23:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(non_snake_case)]` implied by `#[deny(warnings)]` + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/command-line-lint-level-specific-lint.rs b/tests/ui/lint/command-line-lint-level-specific-lint.rs new file mode 100644 index 0000000000000..e3954654fd7bf --- /dev/null +++ b/tests/ui/lint/command-line-lint-level-specific-lint.rs @@ -0,0 +1,11 @@ +// compile-flags: -A warnings -W unused-variables + +fn main() { + let x = 0u8; + //~^ WARNING unused variable + + // Source code lint level should override command-line lint level in any case. + #[deny(unused_variables)] + let y = 0u8; + //~^ ERROR unused variable +} diff --git a/tests/ui/lint/command-line-lint-level-specific-lint.stderr b/tests/ui/lint/command-line-lint-level-specific-lint.stderr new file mode 100644 index 0000000000000..af4985a6c3aa0 --- /dev/null +++ b/tests/ui/lint/command-line-lint-level-specific-lint.stderr @@ -0,0 +1,22 @@ +warning: unused variable: `x` + --> $DIR/command-line-lint-level-specific-lint.rs:4:9 + | +LL | let x = 0u8; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-W unused-variables` + +error: unused variable: `y` + --> $DIR/command-line-lint-level-specific-lint.rs:9:9 + | +LL | let y = 0u8; + | ^ help: if this is intentional, prefix it with an underscore: `_y` + | +note: the lint level is defined here + --> $DIR/command-line-lint-level-specific-lint.rs:8:12 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted +