Treat read of COpy types via refs as not move in move-closure

This commit is contained in:
Aman Arora 2021-02-11 19:36:05 -05:00
parent e39c3c05a4
commit 1b86ad8485
3 changed files with 313 additions and 92 deletions

View File

@ -1116,14 +1116,21 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
place_with_id, diag_expr_id, mode
);
let place = truncate_capture_for_move(place_with_id.place.clone());
match (self.capture_clause, mode) {
// In non-move closures, we only care about moves
(hir::CaptureBy::Ref, euv::Copy) => return,
// We want to capture Copy types that read through a ref via a reborrow
(hir::CaptureBy::Value, euv::Copy)
if place_with_id.place.deref_tys().any(ty::TyS::is_ref) =>
{
return;
}
(hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {}
};
let place = truncate_capture_for_move(place_with_id.place.clone());
let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
if !self.capture_information.contains_key(&place) {

View File

@ -6,7 +6,25 @@
//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#![feature(rustc_attrs)]
// Test we truncate derefs properly
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)] -> ByValue
//~| 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;
@ -24,8 +42,8 @@ fn simple_ref() {
c();
}
// Test we truncate derefs properly
fn struct_contains_ref_to_another_struct() {
// 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);
@ -46,27 +64,78 @@ fn struct_contains_ref_to_another_struct() {
c();
}
// Test that we don't reduce precision when there is nothing deref.
fn no_ref() {
struct S(String);
struct T(S);
// 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 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)] -> ByValue
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
let _t = t.0.0;
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
};
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)] -> ImmBorrow
//~| NOTE: Capturing t[(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);
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)] -> ByValue
//~| NOTE: Capturing b[] -> ByValue
//~| NOTE: Min Capture b[] -> ByValue
};
c();
}
fn main() {
simple_move_closure();
simple_ref();
struct_contains_ref_to_another_struct();
no_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();
}

View File

@ -8,7 +8,7 @@ LL | let mut c = #[rustc_capture_analysis]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:35:17
--> $DIR/move_closure.rs:32:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:55:17
--> $DIR/move_closure.rs:53:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -25,6 +25,33 @@ LL | let mut c = #[rustc_capture_analysis]
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:76:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:98:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/move_closure.rs:119:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/move_closure.rs:3:12
|
@ -40,78 +67,6 @@ error: First Pass analysis includes:
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing ref_s[Deref] -> UniqueImmBorrow
--> $DIR/move_closure.rs:20:9
|
LL | *ref_s += 10;
| ^^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:17:5
|
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture ref_s[Deref] -> UniqueImmBorrow
--> $DIR/move_closure.rs:20:9
|
LL | *ref_s += 10;
| ^^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:38:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
--> $DIR/move_closure.rs:41:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:38:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
--> $DIR/move_closure.rs:41:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:58:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new S".into();
LL | |
LL | |
@ -119,13 +74,13 @@ LL | | };
| |_____^
|
note: Capturing t[(0, 0),(0, 0)] -> ByValue
--> $DIR/move_closure.rs:61:9
--> $DIR/move_closure.rs:20:9
|
LL | t.0.0 = "new S".into();
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:58:5
--> $DIR/move_closure.rs:17:5
|
LL | / move || {
LL | |
@ -137,11 +92,201 @@ LL | | };
| |_____^
|
note: Min Capture t[(0, 0),(0, 0)] -> ByValue
--> $DIR/move_closure.rs:61:9
--> $DIR/move_closure.rs:20:9
|
LL | t.0.0 = "new S".into();
| ^^^^^
error: aborting due to 9 previous errors; 1 warning emitted
error: First Pass analysis includes:
--> $DIR/move_closure.rs:35:5
|
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing ref_s[Deref] -> UniqueImmBorrow
--> $DIR/move_closure.rs:38:9
|
LL | *ref_s += 10;
| ^^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:35:5
|
LL | / move || {
LL | |
LL | |
LL | | *ref_s += 10;
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture ref_s[Deref] -> UniqueImmBorrow
--> $DIR/move_closure.rs:38:9
|
LL | *ref_s += 10;
| ^^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:56:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
--> $DIR/move_closure.rs:59:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:56:5
|
LL | / move || {
LL | |
LL | |
LL | | t.0.0 = "new s".into();
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow
--> $DIR/move_closure.rs:59:9
|
LL | t.0.0 = "new s".into();
| ^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:79:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = t.0.0;
LL | |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
--> $DIR/move_closure.rs:82:18
|
LL | let _t = t.0.0;
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:79:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = t.0.0;
LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
--> $DIR/move_closure.rs:82:18
|
LL | let _t = t.0.0;
| ^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:101:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = t.0.0;
... |
LL | |
LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
--> $DIR/move_closure.rs:104:18
|
LL | let _t = t.0.0;
| ^^^^^
note: Capturing t[(0, 0)] -> ByValue
--> $DIR/move_closure.rs:104:18
|
LL | let _t = t.0.0;
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:101:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = t.0.0;
... |
LL | |
LL | | };
| |_____^
|
note: Min Capture t[(0, 0)] -> ByValue
--> $DIR/move_closure.rs:104:18
|
LL | let _t = t.0.0;
| ^^^^^
error: First Pass analysis includes:
--> $DIR/move_closure.rs:122:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = b.0;
... |
LL | |
LL | | };
| |_____^
|
note: Capturing b[Deref,(0, 0)] -> ByValue
--> $DIR/move_closure.rs:125:18
|
LL | let _t = b.0;
| ^^^
note: Capturing b[] -> ByValue
--> $DIR/move_closure.rs:125:18
|
LL | let _t = b.0;
| ^^^
error: Min Capture analysis includes:
--> $DIR/move_closure.rs:122:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = b.0;
... |
LL | |
LL | | };
| |_____^
|
note: Min Capture b[] -> ByValue
--> $DIR/move_closure.rs:125:18
|
LL | let _t = b.0;
| ^^^
error: aborting due to 18 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0658`.