Implement reborrow for closure captures
This commit is contained in:
parent
d1206f950f
commit
b86c5db96e
6 changed files with 121 additions and 53 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
| ^^^
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue