about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-10-09 16:15:16 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2022-10-09 16:18:16 +0000
commite828ce53b9c9fdcf40d78aed75caf866309a621e (patch)
treec805b467b2e73950cf23e2ada98bca498a0a48c7
parent8796e7a9cfd4c5c4f1de15ec1c53994ddf288665 (diff)
downloadrust-e828ce53b9c9fdcf40d78aed75caf866309a621e.tar.gz
rust-e828ce53b9c9fdcf40d78aed75caf866309a621e.zip
Skip chained OpaqueCast when building captures.
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs15
-rw-r--r--compiler/rustc_mir_build/src/lib.rs1
-rw-r--r--src/test/ui/closures/issue-102089-multiple-opaque-cast.rs17
3 files changed, 25 insertions, 8 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 4d9e9b7c473..396782d45d2 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -17,6 +17,7 @@ use rustc_target::abi::VariantIdx;
 
 use rustc_index::vec::Idx;
 
+use std::assert_matches::assert_matches;
 use std::iter;
 
 /// The "outermost" place that holds this value.
@@ -232,22 +233,20 @@ fn strip_prefix<'tcx>(
     projections: Vec<PlaceElem<'tcx>>,
     prefix_projections: &[HirProjection<'tcx>],
 ) -> impl Iterator<Item = PlaceElem<'tcx>> {
-    let mut iter = projections.into_iter();
-    let mut next = || match iter.next()? {
+    let mut iter = projections
+        .into_iter()
         // Filter out opaque casts, they are unnecessary in the prefix.
-        ProjectionElem::OpaqueCast(..) => iter.next(),
-        other => Some(other),
-    };
+        .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
     for projection in prefix_projections {
         match projection.kind {
             HirProjectionKind::Deref => {
-                assert!(matches!(next(), Some(ProjectionElem::Deref)));
+                assert_matches!(iter.next(), Some(ProjectionElem::Deref));
             }
             HirProjectionKind::Field(..) => {
                 if base_ty.is_enum() {
-                    assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
+                    assert_matches!(iter.next(), Some(ProjectionElem::Downcast(..)));
                 }
-                assert!(matches!(next(), Some(ProjectionElem::Field(..))));
+                assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
             }
             HirProjectionKind::Index | HirProjectionKind::Subslice => {
                 bug!("unexpected projection kind: {:?}", projection);
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 8236b1528c0..b53bd3d0710 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -2,6 +2,7 @@
 //!
 //! This crate also contains the match exhaustiveness and usefulness checking.
 #![allow(rustc::potential_query_instability)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(if_let_guard)]
diff --git a/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs b/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs
new file mode 100644
index 00000000000..043bf06a1f5
--- /dev/null
+++ b/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs
@@ -0,0 +1,17 @@
+// edition:2021
+// check-pass
+
+pub struct Example<'a, T> {
+  a: T,
+  b: &'a T,
+}
+
+impl<'a, T> Example<'a, T> {
+  pub fn error_trying_to_destructure_self_in_closure(self) {
+    let closure = || {
+      let Self { a, b } = self;
+    };
+  }
+}
+
+fn main() {}