about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/levels.rs9
-rw-r--r--compiler/rustc_middle/src/lint.rs31
-rw-r--r--compiler/rustc_session/src/config.rs19
-rw-r--r--compiler/rustc_session/src/options.rs1
-rw-r--r--src/test/ui/lint/force-warn/force-allow-all-warnings.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-allow-all-warnings.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-allow-by-default.rs11
-rw-r--r--src/test/ui/lint/force-warn/force-allow-by-default.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-deny.rs10
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-group.rs12
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-group.stderr12
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-warning.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-warning.stderr10
13 files changed, 146 insertions, 7 deletions
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 91cdef9b089..482ec58fd1a 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -109,6 +109,11 @@ impl<'s> LintLevelsBuilder<'s> {
             }
         }
 
+        for lint_name in &sess.opts.force_warns {
+            store.check_lint_name_cmdline(sess, &lint_name, Level::Allow); // FIXME level is wrong
+            self.sets.force_warns.insert(lint_name.to_uppercase());
+        }
+
         self.sets.list.push(LintSet::CommandLine { specs });
     }
 
@@ -142,6 +147,9 @@ impl<'s> LintLevelsBuilder<'s> {
                     LintLevelSource::Default => false,
                     LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol),
                     LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol),
+                    LintLevelSource::ForceWarn(symbol) => {
+                        bug!("forced warn lint returned a forbid lint level")
+                    }
                 };
                 debug!(
                     "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
@@ -166,6 +174,7 @@ impl<'s> LintLevelsBuilder<'s> {
                         LintLevelSource::CommandLine(_, _) => {
                             diag_builder.note("`forbid` lint level was set on command line");
                         }
+                        _ => bug!("forced warn lint returned a forbid lint level"),
                     }
                     diag_builder.emit();
                 };
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 38d0793a682..af9bc5ebe70 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -1,7 +1,8 @@
 use std::cmp;
 
 use crate::ich::StableHashingContext;
-use rustc_data_structures::fx::FxHashMap;
+use chalk_ir::Substitution;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
@@ -28,6 +29,9 @@ pub enum LintLevelSource {
     /// The provided `Level` is the level specified on the command line.
     /// (The actual level may be lower due to `--cap-lints`.)
     CommandLine(Symbol, Level),
+
+    /// Lint is being forced to warn no matter what.
+    ForceWarn(Symbol),
 }
 
 impl LintLevelSource {
@@ -36,6 +40,7 @@ impl LintLevelSource {
             LintLevelSource::Default => symbol::kw::Default,
             LintLevelSource::Node(name, _, _) => name,
             LintLevelSource::CommandLine(name, _) => name,
+            LintLevelSource::ForceWarn(name) => name,
         }
     }
 
@@ -44,6 +49,7 @@ impl LintLevelSource {
             LintLevelSource::Default => DUMMY_SP,
             LintLevelSource::Node(_, span, _) => span,
             LintLevelSource::CommandLine(_, _) => DUMMY_SP,
+            LintLevelSource::ForceWarn(_) => DUMMY_SP,
         }
     }
 }
@@ -55,6 +61,7 @@ pub type LevelAndSource = (Level, LintLevelSource);
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
     pub lint_cap: Level,
+    pub force_warns: FxHashSet<String>,
 }
 
 #[derive(Debug)]
@@ -73,7 +80,11 @@ pub enum LintSet {
 
 impl LintLevelSets {
     pub fn new() -> Self {
-        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+        LintLevelSets {
+            list: Vec::new(),
+            lint_cap: Level::Forbid,
+            force_warns: FxHashSet::default(),
+        }
     }
 
     pub fn get_lint_level(
@@ -83,6 +94,11 @@ impl LintLevelSets {
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
     ) -> LevelAndSource {
+        // Check whether we should always warn
+        if self.force_warns.contains(lint.name) {
+            return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name)));
+        }
+
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -176,11 +192,11 @@ impl LintLevelMap {
 impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
+        let LintLevelMap { ref sets, ref id_to_set, .. } = *self;
 
         id_to_set.hash_stable(hcx, hasher);
 
-        let LintLevelSets { ref list, lint_cap } = *sets;
+        let LintLevelSets { ref list, lint_cap, .. } = *sets;
 
         lint_cap.hash_stable(hcx, hasher);
 
@@ -346,6 +362,13 @@ pub fn struct_lint_level<'s, 'd>(
                     );
                 }
             }
+            LintLevelSource::ForceWarn(_) => {
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    "Warning forced by `force-warns` commandline option",
+                );
+            }
         }
 
         err.code(DiagnosticId::Lint { name, has_future_breakage });
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 1c6fad2ae8e..5a9da2f2590 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -677,6 +677,7 @@ impl Default for Options {
             optimize: OptLevel::No,
             debuginfo: DebugInfo::None,
             lint_opts: Vec::new(),
+            force_warns: Vec::new(),
             lint_cap: None,
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
@@ -1092,6 +1093,13 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
              level",
             "LEVEL",
         ),
+        opt::multi_s(
+            "",
+            "force-warns",
+            "Specifiy lints that should warn even if \
+             they are allowed somewhere else",
+            "LINT",
+        ),
         opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
         opt::flag_s("V", "version", "Print version info and exit"),
         opt::flag_s("v", "verbose", "Use verbose output"),
@@ -1156,7 +1164,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
-) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
+) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>, Vec<String>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
@@ -1189,7 +1197,10 @@ pub fn get_cmd_lint_options(
         lint::Level::from_str(&cap)
             .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
     });
-    (lint_opts, describe_lints, lint_cap)
+
+    let force_warns = matches.opt_strs("force-warns");
+
+    (lint_opts, describe_lints, lint_cap, force_warns)
 }
 
 /// Parses the `--color` flag.
@@ -1926,7 +1937,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
-    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
+    let (lint_opts, describe_lints, lint_cap, force_warns) =
+        get_cmd_lint_options(matches, error_format);
 
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
@@ -2100,6 +2112,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         optimize: opt_level,
         debuginfo,
         lint_opts,
+        force_warns,
         lint_cap,
         describe_lints,
         output_types,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c9f95ed1224..1d4bb55a22c 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -130,6 +130,7 @@ top_level_options!(
         debuginfo: DebugInfo [TRACKED],
         lint_opts: Vec<(String, lint::Level)> [TRACKED],
         lint_cap: Option<lint::Level> [TRACKED],
+        force_warns: Vec<String> [TRACKED],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
diff --git a/src/test/ui/lint/force-warn/force-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-allow-all-warnings.rs
new file mode 100644
index 00000000000..5501faa437a
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allow-all-warnings.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(warnings)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-allow-all-warnings.stderr
new file mode 100644
index 00000000000..c19f1fe780f
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allow-all-warnings.stderr
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-allow-all-warnings.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: Warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allow-by-default.rs b/src/test/ui/lint/force-warn/force-allow-by-default.rs
new file mode 100644
index 00000000000..d4a5056ddf3
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allow-by-default.rs
@@ -0,0 +1,11 @@
+// compile-flags: --force-warns elided_lifetimes_in_paths
+// check-pass
+
+struct Foo<'a> {
+    x: &'a u32,
+}
+
+fn foo(x: &Foo) {}
+//~^ WARN hidden lifetime parameters in types are deprecated
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allow-by-default.stderr b/src/test/ui/lint/force-warn/force-allow-by-default.stderr
new file mode 100644
index 00000000000..9f62e85e545
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allow-by-default.stderr
@@ -0,0 +1,10 @@
+warning: hidden lifetime parameters in types are deprecated
+  --> $DIR/force-allow-by-default.rs:8:12
+   |
+LL | fn foo(x: &Foo) {}
+   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: Warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allowed-deny.rs b/src/test/ui/lint/force-warn/force-allowed-deny.rs
new file mode 100644
index 00000000000..b34fb5d8b84
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-deny.rs
@@ -0,0 +1,10 @@
+// ignore-test
+// compile-flags: --force-warns arithmetic_overflow
+// check-pass
+
+#![allow(arithmetic_overflow)]
+
+fn main() {
+    1_i32 << 32;
+    //~^ WARN this arithmetic operation will overflow
+}
diff --git a/src/test/ui/lint/force-warn/force-allowed-group.rs b/src/test/ui/lint/force-warn/force-allowed-group.rs
new file mode 100644
index 00000000000..fe8b106a086
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-group.rs
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns bare_trait_objects
+// check-pass
+
+#![allow(rust_2018_compatibility)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-group.stderr b/src/test/ui/lint/force-warn/force-allowed-group.stderr
new file mode 100644
index 00000000000..9fdd998ebf4
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-group.stderr
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-allowed-group.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: Warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = 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-allowed-warning.rs b/src/test/ui/lint/force-warn/force-allowed-warning.rs
new file mode 100644
index 00000000000..5c83c525e38
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-warning.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(dead_code)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.stderr b/src/test/ui/lint/force-warn/force-allowed-warning.stderr
new file mode 100644
index 00000000000..9ae32e89a98
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-warning.stderr
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-allowed-warning.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: Warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+