about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJubilee <46493976+workingjubilee@users.noreply.github.com>2021-10-04 13:58:16 -0700
committerGitHub <noreply@github.com>2021-10-04 13:58:16 -0700
commit3d4467dfcc512fcb2dc2454c9cf77c23ff3de343 (patch)
treec48dd998c239d821f01baa71d55b557ec83d2a44 /compiler
parent5352e17df3b2500b4cf92ee86c7dbf002018600f (diff)
parenta28a78f247a0f02521e97eabf98e790085a4a753 (diff)
downloadrust-3d4467dfcc512fcb2dc2454c9cf77c23ff3de343.tar.gz
rust-3d4467dfcc512fcb2dc2454c9cf77c23ff3de343.zip
Rollup merge of #89500 - FabianWolff:issue-87308, r=petrochenkov
Fix ICE with buffered lint referring to AST node deleted by everybody_loops

Fixes #87308. Note the following comment:
https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_lint/src/early.rs#L415-L417

As it turns out, this is not _always_ a bug, because `-Zunpretty=everybody_loops` causes a lot of AST nodes to be deleted, and thus some buffered lints will refer to non-existent node ids. To fix this, my changes simply ignore buffered lints if `-Zunpretty=everybody_loops` is enabled, which, from my understanding, shouldn't be a big issue because it only affects pretty-printing. Of course, a more elegant solution would only ignore buffered lints that actually point at deleted node ids, but I haven't figured out an easy way of achieving this.

For the concrete example in #87308, the buffered lint is created [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_expand/src/mbe/macro_rules.rs#L145-L151) with the `lint_node_id` from [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_expand/src/mbe/macro_rules.rs#L319), i.e. it points at the macro _expansion_, which then gets deleted by `ReplaceBodyWithLoop` [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_interface/src/passes.rs#L377).
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_interface/src/passes.rs18
1 files changed, 12 insertions, 6 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index a221746f975..2d12ea94a0b 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -437,12 +437,18 @@ pub fn configure_and_expand(
     });
 
     // Add all buffered lints from the `ParseSess` to the `Session`.
-    sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
-        info!("{} parse sess buffered_lints", buffered_lints.len());
-        for early_lint in buffered_lints.drain(..) {
-            resolver.lint_buffer().add_early_lint(early_lint);
-        }
-    });
+    // The ReplaceBodyWithLoop pass may have deleted some AST nodes, potentially
+    // causing a delay_span_bug later if a buffered lint refers to such a deleted
+    // AST node (issue #87308). Since everybody_loops is for pretty-printing only,
+    // anyway, we simply skip all buffered lints here.
+    if !matches!(sess.opts.pretty, Some(PpMode::Source(PpSourceMode::EveryBodyLoops))) {
+        sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
+            info!("{} parse sess buffered_lints", buffered_lints.len());
+            for early_lint in buffered_lints.drain(..) {
+                resolver.lint_buffer().add_early_lint(early_lint);
+            }
+        });
+    }
 
     Ok(krate)
 }