summaryrefslogtreecommitdiffstats
path: root/src/test/ui/closures/2229_closure_analysis/move_closure.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/closures/2229_closure_analysis/move_closure.rs')
-rw-r--r--src/test/ui/closures/2229_closure_analysis/move_closure.rs222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
new file mode 100644
index 000000000..b542fa243
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
@@ -0,0 +1,222 @@
+// edition:2021
+
+// Test that move closures drop derefs with `capture_disjoint_fields` enabled.
+
+#![feature(rustc_attrs)]
+
+fn simple_move_closure() {
+ struct S(String);
+ struct T(S);
+
+ let t = T(S("s".into()));
+ let mut c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ t.0.0 = "new S".into();
+ //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
+ //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
+ };
+ c();
+}
+
+// Test move closure use reborrows when using references
+fn simple_ref() {
+ let mut s = 10;
+ let ref_s = &mut s;
+
+ let mut c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ *ref_s += 10;
+ //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
+ //~| NOTE: Min Capture ref_s[] -> ByValue
+ };
+ c();
+}
+
+// Test move closure use reborrows when using references
+fn struct_contains_ref_to_another_struct_1() {
+ struct S(String);
+ struct T<'a>(&'a mut S);
+
+ let mut s = S("s".into());
+ let t = T(&mut s);
+
+ let mut c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ t.0.0 = "new s".into();
+ //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
+ //~| NOTE: Min Capture t[(0, 0)] -> ByValue
+ };
+
+ c();
+}
+
+// Test that we can use reborrows to read data of Copy types
+// i.e. without truncating derefs
+fn struct_contains_ref_to_another_struct_2() {
+ struct S(i32);
+ struct T<'a>(&'a S);
+
+ let s = S(0);
+ let t = T(&s);
+
+ let mut c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ let _t = t.0.0;
+ //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture t[(0, 0)] -> ByValue
+ };
+
+ c();
+}
+
+// Test that we can use truncate to move out of !Copy types
+fn struct_contains_ref_to_another_struct_3() {
+ struct S(String);
+ struct T<'a>(&'a S);
+
+ let s = S("s".into());
+ let t = T(&s);
+
+ let mut c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ let _t = t.0.0;
+ //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
+ //~| NOTE: Min Capture t[(0, 0)] -> ByValue
+ };
+
+ c();
+}
+
+// Test that derefs of box are truncated in move closures
+fn truncate_box_derefs() {
+ struct S(i32);
+
+
+ // Content within the box is moved within the closure
+ let b = Box::new(S(10));
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ let _t = b.0;
+ //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture b[] -> ByValue
+ };
+
+ c();
+
+ // Content within the box is used by a shared ref and the box is the root variable
+ let b = Box::new(S(10));
+
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ println!("{}", b.0);
+ //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture b[] -> ByValue
+ };
+
+ c();
+
+ // Content within the box is used by a shared ref and the box is not the root variable
+ let b = Box::new(S(10));
+ let t = (0, b);
+
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ move || {
+ //~^ ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ println!("{}", t.1.0);
+ //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture t[(1, 0)] -> ByValue
+ };
+}
+
+struct Foo { x: i32 }
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_1() {
+ let mut foo = Foo { x: 0 } ;
+
+ let p_foo = &mut foo;
+ let box_p_foo = Box::new(p_foo);
+
+ let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| First Pass analysis includes:
+ //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+ //~| Min Capture analysis includes:
+ //~| NOTE: Min Capture box_p_foo[] -> ByValue
+}
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_2() {
+ let foo = Foo { x: 0 } ;
+
+ let mut box_foo = Box::new(foo);
+ let p_foo = &mut box_foo;
+
+ let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| First Pass analysis includes:
+ //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+ //~| Min Capture analysis includes:
+ //~| NOTE: Min Capture p_foo[] -> ByValue
+}
+
+// Test that move closures can take ownership of Copy type
+fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 {
+ let x = 10;
+
+ let c = #[rustc_capture_analysis] move || x;
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| First Pass analysis includes:
+ //~| NOTE: Capturing x[] -> ImmBorrow
+ //~| Min Capture analysis includes:
+ //~| NOTE: Min Capture x[] -> ByValue
+
+ c
+}
+
+fn main() {
+ simple_move_closure();
+ simple_ref();
+ struct_contains_ref_to_another_struct_1();
+ struct_contains_ref_to_another_struct_2();
+ struct_contains_ref_to_another_struct_3();
+ truncate_box_derefs();
+ box_mut_2();
+ box_mut_1();
+}