@@ -7,8 +7,9 @@ use rustc_hir::{HirId, ItemLocalId};
77use rustc_lint_defs:: EditionFcw ;
88use rustc_macros:: { Decodable , Encodable , HashStable } ;
99use rustc_session:: Session ;
10- use rustc_session:: lint:: builtin:: { self , FORBIDDEN_LINT_GROUPS } ;
11- use rustc_session:: lint:: { FutureIncompatibilityReason , Level , Lint , LintExpectationId , LintId } ;
10+ use rustc_session:: lint:: {
11+ FutureIncompatibilityReason , Level , Lint , LintExpectationId , LintId , builtin,
12+ } ;
1213use rustc_span:: { DUMMY_SP , ExpnKind , Span , Symbol , kw} ;
1314use tracing:: instrument;
1415
@@ -89,17 +90,30 @@ pub fn reveal_actual_level(
8990 level. unwrap_or_else ( || ( lint. lint . default_level ( sess. edition ( ) ) , None ) ) ;
9091
9192 // If we're about to issue a warning, check at the last minute for any
92- // directives against the warnings " lint" . If, for example, there's an
93+ // directives against the ` warnings` lint group . If, for example, there's an
9394 // `allow(warnings)` in scope then we want to respect that instead.
94- //
95- // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically
96- // triggers in cases (like #80988) where you have `forbid(warnings)`,
97- // and so if we turned that into an error, it'd defeat the purpose of the
98- // future compatibility warning.
99- if level == Level :: Warn && lint != LintId :: of ( FORBIDDEN_LINT_GROUPS ) {
95+ if level == Level :: Warn {
10096 let ( warnings_level, warnings_src) = probe_for_lint_level ( LintId :: of ( builtin:: WARNINGS ) ) ;
10197 if let Some ( ( configured_warning_level, configured_lint_id) ) = warnings_level {
102- if configured_warning_level != Level :: Warn {
98+ let respect_warnings_lint_group = match configured_warning_level {
99+ // -Wwarnings is a no-op.
100+ Level :: Warn => false ,
101+ // Some warnings cannot be denied from the `warnings` lint group, only individually.
102+ Level :: Deny | Level :: Forbid => !lint. lint . ignore_deny_warnings ,
103+ // All warnings respect -Awarnings.
104+ Level :: Allow => true ,
105+ // Not sure what the right behavior is here, but, sure, why not.
106+ // See tests/ui/lint/rfc-2383-lint-reason/expect_warnings.rs.
107+ Level :: Expect => true ,
108+ Level :: ForceWarn => {
109+ sess. dcx ( ) . span_delayed_bug (
110+ warnings_src. span ( ) ,
111+ "cannot --force-warn the `warnings` lint group" ,
112+ ) ;
113+ false
114+ }
115+ } ;
116+ if respect_warnings_lint_group {
103117 level = configured_warning_level;
104118 lint_id = configured_lint_id;
105119 * src = warnings_src;
@@ -291,6 +305,18 @@ fn explain_lint_level_source(
291305 }
292306 }
293307 }
308+
309+ if let Some ( warnings_group) = sess
310+ . opts
311+ . lint_opts
312+ . iter ( )
313+ . find_map ( |( opt, level) | ( opt == "warnings" ) . then_some ( level) )
314+ . copied ( )
315+ && warnings_group >= Level :: Deny
316+ && level < warnings_group
317+ {
318+ err. note_once ( format ! ( "the `{name}` lint ignores `-D warnings`" ) ) ;
319+ }
294320}
295321
296322/// The innermost function for emitting lints implementing the [`trait@Diagnostic`] trait.
0 commit comments