]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_middle/src/lint.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / lint.rs
index 26e61ec8cf8666483ba5ebb14715069a00bee1f0..4c7ea937ceb7dd1d9f486b05daba3248c89674c7 100644 (file)
@@ -1,7 +1,7 @@
 use std::cmp;
 
 use crate::ich::StableHashingContext;
-use rustc_data_structures::fx::FxHashMap;
+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 +28,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 +39,7 @@ impl LintLevelSource {
             LintLevelSource::Default => symbol::kw::Default,
             LintLevelSource::Node(name, _, _) => name,
             LintLevelSource::CommandLine(name, _) => name,
+            LintLevelSource::ForceWarn(name) => name,
         }
     }
 
@@ -44,6 +48,7 @@ impl LintLevelSource {
             LintLevelSource::Default => DUMMY_SP,
             LintLevelSource::Node(_, span, _) => span,
             LintLevelSource::CommandLine(_, _) => DUMMY_SP,
+            LintLevelSource::ForceWarn(_) => DUMMY_SP,
         }
     }
 }
@@ -55,6 +60,7 @@ pub type LevelAndSource = (Level, LintLevelSource);
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
     pub lint_cap: Level,
+    pub force_warns: FxHashSet<LintId>,
 }
 
 #[derive(Debug)]
@@ -73,7 +79,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 +93,11 @@ impl LintLevelSets {
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
     ) -> LevelAndSource {
+        // Check whether we should always warn
+        if self.force_warns.contains(&LintId::of(lint)) {
+            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 +191,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);
 
@@ -272,11 +287,13 @@ pub fn struct_lint_level<'s, 'd>(
             // emit shouldn't be automatically fixed by rustfix.
             err.allow_suggestions(false);
 
-            // If this is a future incompatible lint it'll become a hard error, so
-            // we have to emit *something*. Also, if this lint occurs in the
-            // expansion of a macro from an external crate, allow individual lints
-            // to opt-out from being reported.
-            if future_incompatible.is_none() && !lint.report_in_external_macro {
+            // If this is a future incompatible that is not an edition fixing lint
+            // it'll become a hard error, so we have to emit *something*. Also,
+            // if this lint occurs in the expansion of a macro from an external crate,
+            // allow individual lints to opt-out from being reported.
+            let not_future_incompatible =
+                future_incompatible.map(|f| f.edition.is_some()).unwrap_or(true);
+            if not_future_incompatible && !lint.report_in_external_macro {
                 err.cancel();
                 // Don't continue further, since we don't want to have
                 // `diag_span_note_once` called for a diagnostic that isn't emitted.
@@ -344,6 +361,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 });
@@ -387,7 +411,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
             false
         }
         ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
-        ExpnKind::Macro(MacroKind::Bang, _) => {
+        ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ } => {
             // Dummy span for the `def_site` means it's an external macro.
             expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site)
         }