diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index c0a059b92aa9f..c7e26013f1cbe 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -11,7 +11,8 @@ use rustc_middle::hir::map::Map; use rustc_middle::lint::LevelAndSource; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::{ - struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, + struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, LintStackIndex, + COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -50,15 +51,15 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { pub struct LintLevelsBuilder<'s> { sess: &'s Session, sets: LintLevelSets, - id_to_set: FxHashMap, - cur: u32, + id_to_set: FxHashMap, + cur: LintStackIndex, warn_about_weird_lints: bool, store: &'s LintStore, crate_attrs: &'s [ast::Attribute], } pub struct BuilderPush { - prev: u32, + prev: LintStackIndex, pub changed: bool, } @@ -72,7 +73,7 @@ impl<'s> LintLevelsBuilder<'s> { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), - cur: 0, + cur: COMMAND_LINE, id_to_set: Default::default(), warn_about_weird_lints, store, @@ -120,7 +121,7 @@ impl<'s> LintLevelsBuilder<'s> { } } - self.sets.list.push(LintSet::CommandLine { specs }); + self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE }); } /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful @@ -523,8 +524,7 @@ impl<'s> LintLevelsBuilder<'s> { let prev = self.cur; if !specs.is_empty() { - self.cur = self.sets.list.len() as u32; - self.sets.list.push(LintSet::Node { specs, parent: prev }); + self.cur = self.sets.list.push(LintSet { specs, parent: prev }); } BuilderPush { prev, changed: prev != self.cur } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 7ac7720a7c563..560581cf641a5 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; +use rustc_index::vec::IndexVec; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, FutureIncompatibilityReason, Level, Lint, LintId, @@ -51,35 +52,37 @@ impl LintLevelSource { /// A tuple of a lint level and its source. pub type LevelAndSource = (Level, LintLevelSource); -#[derive(Debug)] +#[derive(Debug, HashStable)] pub struct LintLevelSets { - pub list: Vec, + pub list: IndexVec, pub lint_cap: Level, } -#[derive(Debug)] -pub enum LintSet { - CommandLine { - // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which - // flag. - specs: FxHashMap, - }, - - Node { - specs: FxHashMap, - parent: u32, - }, +rustc_index::newtype_index! { + #[derive(HashStable)] + pub struct LintStackIndex { + const COMMAND_LINE = 0, + } +} + +#[derive(Debug, HashStable)] +pub struct LintSet { + // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which + // flag. + pub specs: FxHashMap, + + pub parent: LintStackIndex, } impl LintLevelSets { pub fn new() -> Self { - LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid } + LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid } } pub fn get_lint_level( &self, lint: &'static Lint, - idx: u32, + idx: LintStackIndex, aux: Option<&FxHashMap>, sess: &Session, ) -> LevelAndSource { @@ -122,7 +125,7 @@ impl LintLevelSets { pub fn get_lint_id_level( &self, id: LintId, - mut idx: u32, + mut idx: LintStackIndex, aux: Option<&FxHashMap>, ) -> (Option, LintLevelSource) { if let Some(specs) = aux { @@ -131,20 +134,14 @@ impl LintLevelSets { } } loop { - match self.list[idx as usize] { - LintSet::CommandLine { ref specs } => { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - return (None, LintLevelSource::Default); - } - LintSet::Node { ref specs, parent } => { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - idx = parent; - } + let LintSet { ref specs, parent } = self.list[idx]; + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src); + } + if idx == COMMAND_LINE { + return (None, LintLevelSource::Default); } + idx = parent; } } } @@ -152,7 +149,7 @@ impl LintLevelSets { #[derive(Debug)] pub struct LintLevelMap { pub sets: LintLevelSets, - pub id_to_set: FxHashMap, + pub id_to_set: FxHashMap, } impl LintLevelMap { @@ -180,29 +177,7 @@ impl<'a> HashStable> for LintLevelMap { id_to_set.hash_stable(hcx, hasher); - let LintLevelSets { ref list, lint_cap } = *sets; - - lint_cap.hash_stable(hcx, hasher); - - hcx.while_hashing_spans(true, |hcx| { - list.len().hash_stable(hcx, hasher); - - // We are working under the assumption here that the list of - // lint-sets is built in a deterministic order. - for lint_set in list { - ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher); - - match *lint_set { - LintSet::CommandLine { ref specs } => { - specs.hash_stable(hcx, hasher); - } - LintSet::Node { ref specs, parent } => { - specs.hash_stable(hcx, hasher); - parent.hash_stable(hcx, hasher); - } - } - } - }) + hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher)) } }