about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs7
-rw-r--r--tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs15
2 files changed, 21 insertions, 1 deletions
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 956671fc66e..7d99b0e7869 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -218,7 +218,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
             );
         }
         let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take();
-        intravisit::walk_pat(self, p);
+        if let PatKind::Guard(subpat, _) = p.kind {
+            // We'll visit the guard when checking it. Don't gather its locals twice.
+            self.visit_pat(subpat);
+        } else {
+            intravisit::walk_pat(self, p);
+        }
         self.outermost_fn_param_pat = old_outermost_fn_param_pat;
     }
 
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs
new file mode 100644
index 00000000000..7bb39ca7bb9
--- /dev/null
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//! Test that `GatherLocalsVisitor` only visits expressions in guard patterns when checking the
+//! expressions, and not a second time when visiting the pattern. If locals are declared inside the
+//! the guard expression, it would ICE if visited twice ("evaluated expression more than once").
+
+#![feature(guard_patterns)]
+#![expect(incomplete_features)]
+
+fn main() {
+    match (0,) {
+        // FIXME(guard_patterns): liveness lints don't work yet; this will ICE without the `_`.
+        (_ if { let _x = false; _x },) => {}
+        _ => {}
+    }
+}