about summary refs log tree commit diff
diff options
context:
space:
mode:
authordianne <diannes.gm@gmail.com>2025-03-12 23:08:37 -0700
committerdianne <diannes.gm@gmail.com>2025-03-13 01:01:26 -0700
commit36ff87e90e7f39cffb508292a63792cc0dcfbd6e (patch)
treeadb4aa51f09152af238fa2e3aa832ca6114eb23b
parent0e76f8b7e02b1ddd349dde1501f73426a4e764cf (diff)
downloadrust-36ff87e90e7f39cffb508292a63792cc0dcfbd6e.tar.gz
rust-36ff87e90e7f39cffb508292a63792cc0dcfbd6e.zip
EUV: fix place of deref pattern's interior's scrutinee
The place previously used here was that of the temporary holding the
reference returned by `Deref::deref` or `DerefMut::deref_mut`. However,
since the inner pattern of `deref!(inner)` expects the deref-target type
itself, this would ICE when that type was inspected (e.g. by the EUV
case for slice patterns). This adds a deref projection to fix that.

Since current in-tree consumers of EUV (upvar inference and clippy)
don't care about Rvalues, the place could be simplified to
`self.cat_rvalue(pat.hir_id, self.pat_ty_adjusted(subpat)?)` to save
some cycles. I personally find EUV to be a bit fragile, so I've opted
for pedantic correctness. Maybe a `HACK` comment would suffice though?
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs3
-rw-r--r--tests/crashes/125059.rs12
-rw-r--r--tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs15
3 files changed, 17 insertions, 13 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 9ff7eeb2368..ea512130625 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1840,7 +1840,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 let ty = self.pat_ty_adjusted(subpat)?;
                 let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
                 // A deref pattern generates a temporary.
-                let place = self.cat_rvalue(pat.hir_id, ty);
+                let base = self.cat_rvalue(pat.hir_id, ty);
+                let place = self.cat_deref(pat.hir_id, base)?;
                 self.cat_pattern(place, subpat, op)?;
             }
 
diff --git a/tests/crashes/125059.rs b/tests/crashes/125059.rs
deleted file mode 100644
index 7e9f7414816..00000000000
--- a/tests/crashes/125059.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: rust-lang/rust#125059
-#![feature(deref_patterns)]
-#![allow(incomplete_features)]
-
-fn simple_vec(vec: Vec<u32>) -> u32 {
-   (|| match Vec::<u32>::new() {
-        deref!([]) => 100,
-        _ => 2000,
-    })()
-}
-
-fn main() {}
diff --git a/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs
new file mode 100644
index 00000000000..e1a37b9c65f
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//! Regression test for ICE in `rustc_hir_typeck::expr_use_visitor` on nesting a slice pattern
+//! inside a deref pattern inside a closure: rust-lang/rust#125059
+
+#![feature(deref_patterns)]
+#![allow(incomplete_features, unused)]
+
+fn simple_vec(vec: Vec<u32>) -> u32 {
+   (|| match Vec::<u32>::new() {
+        deref!([]) => 100,
+        _ => 2000,
+    })()
+}
+
+fn main() {}