about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-04-09 17:53:10 -0400
committerMichael Goulet <michael@errs.io>2024-04-10 10:13:24 -0400
commit69b690f0f69c7d7bc783df6295bdc6b14d65f07b (patch)
tree74241d4d8081c2ad48846a2231ff7f6fe06ccf03
parentb14d8b2ef20c64c1002e2c6c724025c3d0846b91 (diff)
downloadrust-69b690f0f69c7d7bc783df6295bdc6b14d65f07b.tar.gz
rust-69b690f0f69c7d7bc783df6295bdc6b14d65f07b.zip
Only assert for child/parent projection compatibility AFTER checking that theyre coming from the same place
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs9
-rw-r--r--tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs16
2 files changed, 24 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index ccb229616e8..b26f968bf5e 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -154,6 +154,14 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
             }) {
                 let (child_field_idx, child_capture) = child_captures.next().unwrap();
 
+                // This analysis only makes sense if the parent capture is a
+                // prefix of the child capture.
+                assert!(
+                    child_capture.place.projections.len() >= parent_capture.place.projections.len(),
+                    "parent capture ({parent_capture:#?}) expected to be prefix of \
+                    child capture ({child_capture:#?})"
+                );
+
                 // Store this set of additional projections (fields and derefs).
                 // We need to re-apply them later.
                 let child_precise_captures =
@@ -244,7 +252,6 @@ fn child_prefix_matches_parent_projections(
         bug!("expected capture to be an upvar");
     };
 
-    assert!(child_capture.place.projections.len() >= parent_capture.place.projections.len());
     parent_base.var_path.hir_id == child_base.var_path.hir_id
         && std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
             .all(|(child, parent)| child.kind == parent.kind)
diff --git a/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs b/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs
new file mode 100644
index 00000000000..2313db506be
--- /dev/null
+++ b/tests/ui/async-await/async-closures/different-projection-lengths-for-different-upvars.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+//@ edition: 2021
+// issue: rust-lang/rust#123697
+
+#![feature(async_closure)]
+
+struct S { t: i32 }
+
+fn test(s: &S, t: &i32) {
+    async || {
+        println!("{}", s.t);
+        println!("{}", t);
+    };
+}
+
+fn main() {}