about summary refs log tree commit diff
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
authorxFrednet <xFrednet@gmail.com>2021-11-20 20:45:27 +0100
committerxFrednet <xFrednet@gmail.com>2022-03-02 17:46:08 +0100
commit33a5945069e2c7bd3ba8a0dd65b74ebdd234ad7c (patch)
tree148bd4bf7d42747ed3a2542ca446c429938c4a6c /compiler/rustc_lint
parent44cb8fa482abaa567119ceab125498cfeef1171b (diff)
downloadrust-33a5945069e2c7bd3ba8a0dd65b74ebdd234ad7c.tar.gz
rust-33a5945069e2c7bd3ba8a0dd65b74ebdd234ad7c.zip
Make `LintExpectationId` stable between compilation sessions (RFC-2383)
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r--compiler/rustc_lint/src/early.rs3
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs50
-rw-r--r--compiler/rustc_lint/src/lib.rs2
4 files changed, 48 insertions, 9 deletions
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 1b2c88867d4..e9b7620bf1d 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -59,7 +59,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
         F: FnOnce(&mut Self),
     {
         let is_crate_node = id == ast::CRATE_NODE_ID;
-        let push = self.context.builder.push(attrs, is_crate_node);
+        let push = self.context.builder.push(attrs, is_crate_node, None);
+
         self.check_id(id);
         self.enter_attrs(attrs);
         f(self);
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index a0c8b3501cd..49664322a98 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -25,7 +25,7 @@ pub fn check_expectations(tcx: TyCtxt<'_>) {
 }
 
 fn emit_unfulfilled_expectation_lint(tcx: TyCtxt<'_>, expectation: &LintExpectation) {
-    // FIXME  The current implementation doesn't cover cases where the
+    // FIXME: The current implementation doesn't cover cases where the
     // `unfulfilled_lint_expectations` is actually expected by another lint
     // expectation. This can be added here as we have the lint level of this
     // expectation, and we can also mark the lint expectation it would fulfill
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index a876e35c0a8..417022bd2bf 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -32,17 +32,23 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
 
     builder.levels.id_to_set.reserve(krate.owners.len() + 1);
 
-    let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true);
+    let push =
+        builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true, Some(hir::CRATE_HIR_ID));
+
     builder.levels.register_id(hir::CRATE_HIR_ID);
     tcx.hir().walk_toplevel_module(&mut builder);
     builder.levels.pop(push);
 
+    builder.levels.update_unstable_expectation_ids();
     builder.levels.build_map()
 }
 
 pub struct LintLevelsBuilder<'s> {
     sess: &'s Session,
     lint_expectations: FxHashMap<LintExpectationId, LintExpectation>,
+    /// Each expectation has a stable and an unstable identifier. This map
+    /// is used to map from unstable to stable [`LintExpectationId`]s.
+    expectation_id_map: FxHashMap<LintExpectationId, LintExpectationId>,
     sets: LintLevelSets,
     id_to_set: FxHashMap<HirId, LintStackIndex>,
     cur: LintStackIndex,
@@ -66,6 +72,7 @@ impl<'s> LintLevelsBuilder<'s> {
         let mut builder = LintLevelsBuilder {
             sess,
             lint_expectations: Default::default(),
+            expectation_id_map: Default::default(),
             sets: LintLevelSets::new(),
             cur: COMMAND_LINE,
             id_to_set: Default::default(),
@@ -226,13 +233,26 @@ impl<'s> LintLevelsBuilder<'s> {
     ///   `#[allow]`
     ///
     /// Don't forget to call `pop`!
-    pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) -> BuilderPush {
+    pub(crate) fn push(
+        &mut self,
+        attrs: &[ast::Attribute],
+        is_crate_node: bool,
+        source_hir_id: Option<HirId>,
+    ) -> BuilderPush {
         let mut specs = FxHashMap::default();
         let sess = self.sess;
         let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
-        for attr in attrs {
-            let Some(level) = Level::from_symbol(attr.name_or_empty(), attr.id.as_u32()) else {
-                continue
+        for (attr_index, attr) in attrs.iter().enumerate() {
+            let level = match Level::from_symbol(attr.name_or_empty(), || {
+                LintExpectationId::Unstable(attr.id)
+            }) {
+                None => continue,
+                Some(Level::Expect(unstable_id)) if source_hir_id.is_some() => {
+                    let stable_id =
+                        self.create_stable_id(unstable_id, source_hir_id.unwrap(), attr_index);
+                    Level::Expect(stable_id)
+                }
+                Some(lvl) => lvl,
             };
 
             let Some(mut metas) = attr.meta_item_list() else {
@@ -539,6 +559,19 @@ impl<'s> LintLevelsBuilder<'s> {
         BuilderPush { prev, changed: prev != self.cur }
     }
 
+    fn create_stable_id(
+        &mut self,
+        unstable_id: LintExpectationId,
+        hir_id: HirId,
+        attr_index: usize,
+    ) -> LintExpectationId {
+        let stable_id = LintExpectationId::Stable { hir_id, attr_index };
+
+        self.expectation_id_map.insert(unstable_id, stable_id);
+
+        stable_id
+    }
+
     /// Checks if the lint is gated on a feature that is not enabled.
     fn check_gated_lint(&self, lint_id: LintId, span: Span) {
         if let Some(feature) = lint_id.lint.feature_gate {
@@ -582,6 +615,10 @@ impl<'s> LintLevelsBuilder<'s> {
         self.id_to_set.insert(id, self.cur);
     }
 
+    fn update_unstable_expectation_ids(&self) {
+        self.sess.diagnostic().update_unstable_expectation_id(&self.expectation_id_map);
+    }
+
     pub fn build_map(self) -> LintLevelMap {
         LintLevelMap {
             sets: self.sets,
@@ -603,7 +640,8 @@ impl LintLevelMapBuilder<'_> {
     {
         let is_crate_hir = id == hir::CRATE_HIR_ID;
         let attrs = self.tcx.hir().attrs(id);
-        let push = self.levels.push(attrs, is_crate_hir);
+        let push = self.levels.push(attrs, is_crate_hir, Some(id));
+
         if push.changed {
             self.levels.register_id(id);
         }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 2dc6e980722..18f229564c2 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -51,8 +51,8 @@ pub mod builtin;
 mod context;
 mod early;
 mod enum_intrinsics_non_enums;
-pub mod hidden_unicode_codepoints;
 mod expect;
+pub mod hidden_unicode_codepoints;
 mod internal;
 mod late;
 mod levels;