1
Fork 0

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 place_with_id, diag_expr_id, mode
); );
let place = truncate_capture_for_move(place_with_id.place.clone());
match (self.capture_clause, mode) { match (self.capture_clause, mode) {
// In non-move closures, we only care about moves // In non-move closures, we only care about moves
(hir::CaptureBy::Ref, euv::Copy) => return, (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) => {} (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 }; let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
if !self.capture_information.contains_key(&place) { 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> //~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488>
#![feature(rustc_attrs)] #![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() { fn simple_ref() {
let mut s = 10; let mut s = 10;
let ref_s = &mut s; let ref_s = &mut s;
@ -24,8 +42,8 @@ fn simple_ref() {
c(); c();
} }
// Test we truncate derefs properly // Test move closure use reborrows when using references
fn struct_contains_ref_to_another_struct() { fn struct_contains_ref_to_another_struct_1() {
struct S(String); struct S(String);
struct T<'a>(&'a mut S); struct T<'a>(&'a mut S);
@ -46,27 +64,78 @@ fn struct_contains_ref_to_another_struct() {
c(); c();
} }
// Test that we don't reduce precision when there is nothing deref. // Test that we can use reborrows to read data of Copy types
fn no_ref() { // i.e. without truncating derefs
struct S(String); fn struct_contains_ref_to_another_struct_2() {
struct T(S); 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] let mut c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental //~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
move || { move || {
//~^ ERROR: First Pass analysis includes: //~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes: //~| ERROR: Min Capture analysis includes:
t.0.0 = "new S".into(); let _t = t.0.0;
//~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue //~| 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(); c();
} }
fn main() { fn main() {
simple_move_closure();
simple_ref(); simple_ref();
struct_contains_ref_to_another_struct(); struct_contains_ref_to_another_struct_1();
no_ref(); 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 = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental 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] 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 = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental 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] 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 = 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 = 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 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 --> $DIR/move_closure.rs:3:12
| |
@ -40,78 +67,6 @@ error: First Pass analysis includes:
LL | / move || { LL | / move || {
LL | | LL | |
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 | | t.0.0 = "new S".into();
LL | | LL | |
LL | | LL | |
@ -119,13 +74,13 @@ LL | | };
| |_____^ | |_____^
| |
note: Capturing t[(0, 0),(0, 0)] -> ByValue 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(); LL | t.0.0 = "new S".into();
| ^^^^^ | ^^^^^
error: Min Capture analysis includes: error: Min Capture analysis includes:
--> $DIR/move_closure.rs:58:5 --> $DIR/move_closure.rs:17:5
| |
LL | / move || { LL | / move || {
LL | | LL | |
@ -137,11 +92,201 @@ LL | | };
| |_____^ | |_____^
| |
note: Min Capture t[(0, 0),(0, 0)] -> ByValue 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(); 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`. For more information about this error, try `rustc --explain E0658`.