about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAman Arora <me@aman-arora.com>2021-02-04 02:12:31 -0500
committerAman Arora <me@aman-arora.com>2021-02-15 22:00:25 -0500
commitb86c5db96eecbf6f4b08cd3f29d5a5b4dae13aee (patch)
tree9a460ae26b0e84af8ccd72f785224a6355b0cafd /src
parentd1206f950ffb76c76e1b74a19ae33c2b7d949454 (diff)
downloadrust-b86c5db96eecbf6f4b08cd3f29d5a5b4dae13aee.tar.gz
rust-b86c5db96eecbf6f4b08cd3f29d5a5b4dae13aee.zip
Implement reborrow for closure captures
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/closures/2229_closure_analysis/by_value.rs3
-rw-r--r--src/test/ui/closures/2229_closure_analysis/by_value.stderr11
-rw-r--r--src/test/ui/closures/2229_closure_analysis/move_closure.rs8
-rw-r--r--src/test/ui/closures/2229_closure_analysis/move_closure.stderr8
-rw-r--r--src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs41
5 files changed, 59 insertions, 12 deletions
diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.rs b/src/test/ui/closures/2229_closure_analysis/by_value.rs
index 1007fb582e5..27c8fb1363f 100644
--- a/src/test/ui/closures/2229_closure_analysis/by_value.rs
+++ b/src/test/ui/closures/2229_closure_analysis/by_value.rs
@@ -26,7 +26,8 @@ fn big_box() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         let p = t.0.0;
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+        //~| NOTE: Capturing t[(0, 0)] -> ByValue
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
         println!("{} {:?}", t.1, p);
         //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/by_value.stderr
index fe04dbef6d8..944e4c40a78 100644
--- a/src/test/ui/closures/2229_closure_analysis/by_value.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/by_value.stderr
@@ -28,13 +28,18 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+  --> $DIR/by_value.rs:28:17
+   |
+LL |         let p = t.0.0;
+   |                 ^^^^^
+note: Capturing t[(0, 0)] -> ByValue
   --> $DIR/by_value.rs:28:17
    |
 LL |         let p = t.0.0;
    |                 ^^^^^
 note: Capturing t[(1, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:31:29
+  --> $DIR/by_value.rs:32:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
@@ -57,7 +62,7 @@ note: Min Capture t[(0, 0)] -> ByValue
 LL |         let p = t.0.0;
    |                 ^^^^^
 note: Min Capture t[(1, 0)] -> ImmBorrow
-  --> $DIR/by_value.rs:31:29
+  --> $DIR/by_value.rs:32:29
    |
 LL |         println!("{} {:?}", t.1, p);
    |                             ^^^
diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
index 8bdc999ca3c..d57c2280438 100644
--- a/src/test/ui/closures/2229_closure_analysis/move_closure.rs
+++ b/src/test/ui/closures/2229_closure_analysis/move_closure.rs
@@ -18,8 +18,8 @@ fn simple_ref() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         *ref_s += 10;
-        //~^ NOTE: Capturing ref_s[Deref] -> ByValue
-        //~| NOTE: Min Capture ref_s[] -> ByValue
+        //~^ NOTE: Capturing ref_s[Deref] -> UniqueImmBorrow
+        //~| NOTE: Min Capture ref_s[Deref] -> UniqueImmBorrow
     };
     c();
 }
@@ -39,8 +39,8 @@ fn struct_contains_ref_to_another_struct() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new s".into();
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
-        //~| NOTE: Min Capture t[(0, 0)] -> ByValue
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
+        //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
     };
 
     c();
diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
index a745f14598e..554dc11f6ba 100644
--- a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr
@@ -46,7 +46,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing ref_s[Deref] -> ByValue
+note: Capturing ref_s[Deref] -> UniqueImmBorrow
   --> $DIR/move_closure.rs:20:9
    |
 LL |         *ref_s += 10;
@@ -64,7 +64,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture ref_s[] -> ByValue
+note: Min Capture ref_s[Deref] -> UniqueImmBorrow
   --> $DIR/move_closure.rs:20:9
    |
 LL |         *ref_s += 10;
@@ -82,7 +82,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
   --> $DIR/move_closure.rs:41:9
    |
 LL |         t.0.0 = "new s".into();
@@ -100,7 +100,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0)] -> ByValue
+note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
   --> $DIR/move_closure.rs:41:9
    |
 LL |         t.0.0 = "new s".into();
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
index 4007a5a48aa..afaafbda018 100644
--- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
+++ b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
@@ -56,9 +56,50 @@ fn no_ref_nested() {
     c();
 }
 
+struct A<'a>(&'a mut String,  &'a mut String);
+// Test that reborrowing works as expected for move closures
+// by attempting a disjoint capture through a reference.
+fn disjoint_via_ref() {
+    let mut x = String::new();
+    let mut y = String::new();
+
+    let mut a = A(&mut x, &mut y);
+    let a = &mut a;
+
+    let mut c1 = move || {
+        a.0.truncate(0);
+    };
+
+    let mut c2 = move || {
+        a.1.truncate(0);
+    };
+
+    c1();
+    c2();
+}
+
+// Test that even if a path is moved into the closure, the closure is not FnOnce
+// if the path is not moved by the closure call.
+fn data_moved_but_not_fn_once() {
+    let x = Box::new(10i32);
+
+    let c = move || {
+        // *x has type i32 which is Copy. So even though the box `x` will be moved
+        // into the closure, `x` is never moved when the closure is called, i.e. the
+        // ownership stays with the closure and therefore we can call the function multiple times.
+        let _x = *x;
+    };
+
+    c();
+    c();
+}
+
 fn main() {
     simple_ref();
     struct_contains_ref_to_another_struct();
     no_ref();
     no_ref_nested();
+
+    disjoint_via_ref();
+    data_moved_but_not_fn_once();
 }