From a3d6905053ad60e836717976e6e4d38de67888f9 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Fri, 4 Jun 2021 14:37:20 +0200 Subject: [PATCH 1/3] Force warnings even when can_emit_warnings == false --- .../src/annotate_snippet_emitter_writer.rs | 5 +++-- compiler/rustc_errors/src/diagnostic.rs | 9 ++++++++- compiler/rustc_errors/src/json.rs | 2 +- compiler/rustc_errors/src/lib.rs | 7 +++++-- compiler/rustc_middle/src/lint.rs | 15 ++++++++++++++- compiler/rustc_session/src/session.rs | 2 +- .../ui/lint/force-warn/force-warns-cap-lints.rs | 10 ++++++++++ .../lint/force-warn/force-warns-cap-lints.stderr | 12 ++++++++++++ 8 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/lint/force-warn/force-warns-cap-lints.rs create mode 100644 src/test/ui/lint/force-warn/force-warns-cap-lints.stderr diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 577baec21f064..2253007ce3027 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -145,8 +145,9 @@ impl AnnotateSnippetEmitterWriter { title: Some(Annotation { label: Some(&message), id: code.as_ref().map(|c| match c { - DiagnosticId::Error(val) - | DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(), + DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => { + val.as_str() + } }), annotation_type: annotation_type_for_level(*level), }), diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 14ccced2c6a56..45661ac15623f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -29,7 +29,7 @@ pub struct Diagnostic { #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticId { Error(String), - Lint { name: String, has_future_breakage: bool }, + Lint { name: String, has_future_breakage: bool, is_force_warn: bool }, } /// A "sub"-diagnostic attached to a parent diagnostic. @@ -109,6 +109,13 @@ impl Diagnostic { } } + pub fn is_force_warn(&self) -> bool { + match self.code { + Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn, + _ => false, + } + } + /// Cancel the diagnostic (a structured diagnostic must either be emitted or /// canceled or it will panic when dropped). pub fn cancel(&mut self) { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 72395bd31eca5..485e7564587ea 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -559,7 +559,7 @@ impl DiagnosticCode { s.map(|s| { let s = match s { DiagnosticId::Error(s) => s, - DiagnosticId::Lint { name, has_future_breakage: _ } => name, + DiagnosticId::Lint { name, .. } => name, }; let je_result = je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 979f2d3b3005d..c5399282a1e1a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -802,7 +802,10 @@ impl HandlerInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } - if diagnostic.level == Warning && !self.flags.can_emit_warnings { + if diagnostic.level == Warning + && !self.flags.can_emit_warnings + && !diagnostic.is_force_warn() + { if diagnostic.has_future_breakage() { (*TRACK_DIAGNOSTICS)(diagnostic); } @@ -874,7 +877,7 @@ impl HandlerInner { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => self.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)), + (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)), (_, 0) => { let _ = self.fatal(&errors); } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 7ac7720a7c563..71cf5b2249c38 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -246,6 +246,9 @@ pub fn struct_lint_level<'s, 'd>( let has_future_breakage = future_incompatible.map_or(false, |incompat| incompat.future_breakage.is_some()); + let is_force_warn = matches!(level, Level::ForceWarn) + || matches!(src, LintLevelSource::CommandLine(_, Level::ForceWarn)); + let mut err = match (level, span) { (Level::Allow, span) => { if has_future_breakage { @@ -254,6 +257,16 @@ pub fn struct_lint_level<'s, 'd>( } else { sess.struct_allow("") } + } else if is_force_warn { + let mut err = if let Some(span) = span { + sess.struct_span_warn(span, "") + } else { + sess.struct_warn("") + }; + // Ensure force-warn warns even if the diagnostic has + // been canceled for reasons like `--cap-lints` + err.level = rustc_errors::Level::Warning; + err } else { return; } @@ -349,7 +362,7 @@ pub fn struct_lint_level<'s, 'd>( } } - err.code(DiagnosticId::Lint { name, has_future_breakage }); + err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); if let Some(future_incompatible) = future_incompatible { let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d8a58ee18cd8e..2bcb7c94d5350 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -323,7 +323,7 @@ impl Session { .into_iter() .map(|diag| { let lint_name = match &diag.code { - Some(DiagnosticId::Lint { name, has_future_breakage: true }) => name, + Some(DiagnosticId::Lint { name, has_future_breakage: true, .. }) => name, _ => panic!("Unexpected code in diagnostic {:?}", diag), }; let lint = lint_store.name_to_lint(&lint_name); diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints.rs b/src/test/ui/lint/force-warn/force-warns-cap-lints.rs new file mode 100644 index 0000000000000..e364897ec4ecb --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warns-cap-lints.rs @@ -0,0 +1,10 @@ +// compile-flags: --cap-lints allow --force-warns bare_trait_objects -Zunstable-options +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints.stderr b/src/test/ui/lint/force-warn/force-warns-cap-lints.stderr new file mode 100644 index 0000000000000..73971e9d4e505 --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warns-cap-lints.stderr @@ -0,0 +1,12 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/force-warns-cap-lints.rs:6:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` + | + = note: requested on the command line with `--force-warns bare-trait-objects` + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see issue #80165 + +warning: 1 warning emitted + From 33cc7b1fe21c82d31204e549cd2471ac8ec22aa3 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Thu, 1 Jul 2021 12:29:20 +0200 Subject: [PATCH 2/3] New force_warn diagnostic builder and ensure cap-lints doesn't reduce force_warn level --- compiler/rustc_errors/src/lib.rs | 18 +++++++++++++ compiler/rustc_middle/src/lint.rs | 25 ++++++++----------- compiler/rustc_session/src/session.rs | 10 ++++++++ .../force-warn/force-warn-cap-lints-warn.rs | 15 +++++++++++ .../force-warn-cap-lints-warn.stderr | 12 +++++++++ ...ints.rs => force-warns-cap-lints-allow.rs} | 0 ...err => force-warns-cap-lints-allow.stderr} | 2 +- 7 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr rename src/test/ui/lint/force-warn/{force-warns-cap-lints.rs => force-warns-cap-lints-allow.rs} (100%) rename src/test/ui/lint/force-warn/{force-warns-cap-lints.stderr => force-warns-cap-lints-allow.stderr} (91%) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index c5399282a1e1a..a5e11541c8b4c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -521,12 +521,24 @@ impl Handler { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// Cancel the builder if warnings cannot be emitted pub fn struct_span_warn(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { let mut result = self.struct_warn(msg); result.set_span(span); result } + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + pub fn struct_span_force_warn( + &self, + span: impl Into, + msg: &str, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_force_warn(msg); + result.set_span(span); + result + } + /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. pub fn struct_span_allow( &self, @@ -552,6 +564,7 @@ impl Handler { } /// Construct a builder at the `Warning` level with the `msg`. + /// Cancel the builder if warnings cannot be emitted pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); if !self.flags.can_emit_warnings { @@ -560,6 +573,11 @@ impl Handler { result } + /// Construct a builder at the `Warning` level with the `msg`. + pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Level::Warning, msg) + } + /// Construct a builder at the `Allow` level with the `msg`. pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Allow, msg) diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 71cf5b2249c38..b5eab8be17fb8 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -108,8 +108,13 @@ impl LintLevelSets { } } - // Ensure that we never exceed the `--cap-lints` argument. - level = cmp::min(level, self.lint_cap); + // Ensure that we never exceed the `--cap-lints` argument + // unless the source is a --force-warn + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src { + level + } else { + cmp::min(level, self.lint_cap) + }; if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) { // Ensure that we never exceed driver level. @@ -257,22 +262,14 @@ pub fn struct_lint_level<'s, 'd>( } else { sess.struct_allow("") } - } else if is_force_warn { - let mut err = if let Some(span) = span { - sess.struct_span_warn(span, "") - } else { - sess.struct_warn("") - }; - // Ensure force-warn warns even if the diagnostic has - // been canceled for reasons like `--cap-lints` - err.level = rustc_errors::Level::Warning; - err } else { return; } } - (Level::Warn | Level::ForceWarn, Some(span)) => sess.struct_span_warn(span, ""), - (Level::Warn | Level::ForceWarn, None) => sess.struct_warn(""), + (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), + (Level::Warn, None) => sess.struct_warn(""), + (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""), + (Level::ForceWarn, None) => sess.struct_force_warn(""), (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), (Level::Deny | Level::Forbid, None) => sess.struct_err(""), }; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 2bcb7c94d5350..f6b7797c2e3b1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -369,6 +369,13 @@ impl Session { pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_span_warn(sp, msg) } + pub fn struct_span_force_warn>( + &self, + sp: S, + msg: &str, + ) -> DiagnosticBuilder<'_> { + self.diagnostic().struct_span_force_warn(sp, msg) + } pub fn struct_span_warn_with_code>( &self, sp: S, @@ -380,6 +387,9 @@ impl Session { pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_warn(msg) } + pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { + self.diagnostic().struct_force_warn(msg) + } pub fn struct_span_allow>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_span_allow(sp, msg) } diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs new file mode 100644 index 0000000000000..bcfe6e5a5bd6e --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs @@ -0,0 +1,15 @@ +// compile-flags: --cap-lints warn --force-warns rust-2021-compatibility -Zunstable-options +// check-pass +#![allow(ellipsis_inclusive_range_patterns)] + +pub fn f() -> bool { + let x = 123; + match x { + 0...100 => true, + //~^ WARN range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => false, + } +} + +fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr new file mode 100644 index 0000000000000..07e786ce7d266 --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr @@ -0,0 +1,12 @@ +warning: `...` range patterns are deprecated + --> $DIR/force-warn-cap-lints-warn.rs:8:10 + | +LL | 0...100 => true, + | ^^^ help: use `..=` for an inclusive range + | + = note: `--force-warns ellipsis-inclusive-range-patterns` implied by `--force-warns rust-2021-compatibility` + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see issue #80165 + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints.rs b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs similarity index 100% rename from src/test/ui/lint/force-warn/force-warns-cap-lints.rs rename to src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints.stderr b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr similarity index 91% rename from src/test/ui/lint/force-warn/force-warns-cap-lints.stderr rename to src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr index 73971e9d4e505..21532024f1c4a 100644 --- a/src/test/ui/lint/force-warn/force-warns-cap-lints.stderr +++ b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr @@ -1,5 +1,5 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/force-warns-cap-lints.rs:6:25 + --> $DIR/force-warns-cap-lints-allow.rs:6:25 | LL | pub fn function(_x: Box) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` From 5af5a6d49dd5a72c7c4f48ba9749b84002e0b99e Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 6 Jul 2021 13:47:03 +0200 Subject: [PATCH 3/3] Add missing docs and remove dead code --- compiler/rustc_errors/src/lib.rs | 12 ++++++++++-- compiler/rustc_middle/src/lint.rs | 4 +--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a5e11541c8b4c..323415f3300b2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -521,7 +521,8 @@ impl Handler { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// Cancel the builder if warnings cannot be emitted + /// + /// The builder will be canceled if warnings cannot be emitted. pub fn struct_span_warn(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { let mut result = self.struct_warn(msg); result.set_span(span); @@ -529,6 +530,9 @@ impl Handler { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// + /// This will "force" the warning meaning it will not be canceled even + /// if warnings cannot be emitted. pub fn struct_span_force_warn( &self, span: impl Into, @@ -564,7 +568,8 @@ impl Handler { } /// Construct a builder at the `Warning` level with the `msg`. - /// Cancel the builder if warnings cannot be emitted + /// + /// The builder will be canceled if warnings cannot be emitted. pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); if !self.flags.can_emit_warnings { @@ -574,6 +579,9 @@ impl Handler { } /// Construct a builder at the `Warning` level with the `msg`. + /// + /// This will "force" a warning meaning it will not be canceled even + /// if warnings cannot be emitted. pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Warning, msg) } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index b5eab8be17fb8..efd8d56fd6fdd 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -251,9 +251,6 @@ pub fn struct_lint_level<'s, 'd>( let has_future_breakage = future_incompatible.map_or(false, |incompat| incompat.future_breakage.is_some()); - let is_force_warn = matches!(level, Level::ForceWarn) - || matches!(src, LintLevelSource::CommandLine(_, Level::ForceWarn)); - let mut err = match (level, span) { (Level::Allow, span) => { if has_future_breakage { @@ -359,6 +356,7 @@ pub fn struct_lint_level<'s, 'd>( } } + let is_force_warn = matches!(level, Level::ForceWarn); err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); if let Some(future_incompatible) = future_incompatible {