about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-06 16:50:33 +0000
committerbors <bors@rust-lang.org>2021-07-06 16:50:33 +0000
commit238fd72880776c5dbd3b067acb096562e6af5399 (patch)
treeedf6a2c2caf93943ea31145691d962592833a3e8
parentb09dad3eddfc46c55e45f6c1a00bab09401684b4 (diff)
parent5af5a6d49dd5a72c7c4f48ba9749b84002e0b99e (diff)
downloadrust-238fd72880776c5dbd3b067acb096562e6af5399.tar.gz
rust-238fd72880776c5dbd3b067acb096562e6af5399.zip
Auto merge of #86572 - rylev:force-warnings-always, r=nikomatsakis
Force warnings even when can_emit_warnings == false

Fixes an issue mentioned in #85512 with --cap-lints overriding --force-warnings.

Fixes https://github.com/rust-lang/rust/issues/86751

r? `@ehuss`
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs5
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs9
-rw-r--r--compiler/rustc_errors/src/json.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs33
-rw-r--r--compiler/rustc_middle/src/lint.rs18
-rw-r--r--compiler/rustc_session/src/session.rs12
-rw-r--r--src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs15
-rw-r--r--src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr12
-rw-r--r--src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs10
-rw-r--r--src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr12
10 files changed, 116 insertions, 12 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index 577baec21f0..2253007ce30 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 14ccced2c6a..45661ac1562 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 72395bd31ec..485e7564587 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 ca2386dfae2..f8339d6e3f4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -520,12 +520,28 @@ impl Handler {
     }
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
+    ///
+    /// The builder will be canceled if warnings cannot be emitted.
     pub fn struct_span_warn(&self, span: impl Into<MultiSpan>, 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`.
+    ///
+    /// 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<MultiSpan>,
+        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,
@@ -551,6 +567,8 @@ impl Handler {
     }
 
     /// Construct a builder at the `Warning` level with the `msg`.
+    ///
+    /// 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 {
@@ -559,6 +577,14 @@ impl Handler {
         result
     }
 
+    /// 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)
+    }
+
     /// Construct a builder at the `Allow` level with the `msg`.
     pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> {
         DiagnosticBuilder::new(self, Level::Allow, msg)
@@ -801,7 +827,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);
             }
@@ -873,7 +902,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 560581cf641..c9b6cee5deb 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -111,8 +111,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.
@@ -233,8 +238,10 @@ pub fn struct_lint_level<'s, 'd>(
                     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(""),
         };
@@ -324,7 +331,8 @@ pub fn struct_lint_level<'s, 'd>(
             }
         }
 
-        err.code(DiagnosticId::Lint { name, has_future_breakage });
+        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 {
             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 f81176f2180..8270bbbe8fd 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -324,7 +324,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);
@@ -351,6 +351,13 @@ impl Session {
     pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
+    pub fn struct_span_force_warn<S: Into<MultiSpan>>(
+        &self,
+        sp: S,
+        msg: &str,
+    ) -> DiagnosticBuilder<'_> {
+        self.diagnostic().struct_span_force_warn(sp, msg)
+    }
     pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -362,6 +369,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<S: Into<MultiSpan>>(&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 00000000000..bcfe6e5a5bd
--- /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 00000000000..07e786ce7d2
--- /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 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.rs
new file mode 100644
index 00000000000..e364897ec4e
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.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<SomeTrait>) {}
+//~^ 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-allow.stderr b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr
new file mode 100644
index 00000000000..21532024f1c
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warns-cap-lints-allow.stderr
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warns-cap-lints-allow.rs:6:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ 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 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+