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;
/// 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 {
LintLevelSource::Default => symbol::kw::Default,
LintLevelSource::Node(name, _, _) => name,
LintLevelSource::CommandLine(name, _) => name,
+ LintLevelSource::ForceWarn(name) => name,
}
}
LintLevelSource::Default => DUMMY_SP,
LintLevelSource::Node(_, span, _) => span,
LintLevelSource::CommandLine(_, _) => DUMMY_SP,
+ LintLevelSource::ForceWarn(_) => DUMMY_SP,
}
}
}
pub struct LintLevelSets {
pub list: Vec<LintSet>,
pub lint_cap: Level,
+ pub force_warns: FxHashSet<LintId>,
}
#[derive(Debug)]
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(
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
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);
// 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.
);
}
}
+ 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 });
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)
}