Implement reborrow for closure captures

This commit is contained in:
Aman Arora 2021-02-04 02:12:31 -05:00
parent d1206f950f
commit b86c5db96e
6 changed files with 121 additions and 53 deletions

View file

@ -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

View file

@ -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);
| ^^^

View file

@ -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();

View file

@ -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();

View file

@ -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();
}