Skip to content

Commit 799bf49

Browse files
P8L1frank-king
authored andcommitted
Skip long-lived pin facts for Unpin places
1 parent 61db175 commit 799bf49

9 files changed

Lines changed: 93 additions & 55 deletions

File tree

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Pins<'_, 'tcx> {
760760
if let mir::Rvalue::Ref(_, mir::BorrowKind::Pinned(_, kind), place) = rhs
761761
&& matches!(*kind, mir::PinBorrowKind::Persistent)
762762
{
763-
self.gen_pins_on_place(state, *place);
763+
let place_ty = place.ty(self.body, self.tcx).ty;
764+
if !place_ty.is_unpin(self.tcx, self.body.typing_env(self.tcx)) {
765+
self.gen_pins_on_place(state, *place);
766+
}
764767
}
765768
}
766769

compiler/rustc_borrowck/src/lib.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,17 +1274,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
12741274
&self,
12751275
state: &'s BorrowckDomain,
12761276
) -> Option<&'s MixedBitSet<BorrowIndex>> {
1277-
// FIXME(pin_ergonomics): borrowck behaviors depend on a safe trait
1278-
// which should not contain any safety invariants.
1279-
// if place
1280-
// .ty(self.body, self.infcx.tcx)
1281-
// .ty
1282-
// .is_unpin(self.infcx.tcx, self.body.typing_env(self.infcx.tcx))
1283-
// {
1284-
// None
1285-
// } else {
12861277
Some(&state.pinned_borrows)
1287-
// }
12881278
}
12891279

12901280
#[instrument(level = "debug", skip(self, state))]

tests/ui/pin-ergonomics/borrow-pinned-projection.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
// of `pair.0` until reassignment.
77

88
#[pin_v2]
9-
struct Foo;
9+
#[derive(Default)]
10+
struct Foo(std::marker::PhantomPinned);
1011

1112
fn mutable_borrow_of_pinned_projection() {
12-
let mut pair = (Foo, Foo);
13+
let mut pair = (Foo::default(), Foo::default());
1314

1415
{
1516
let _pin = &pin mut pair.0;
@@ -21,7 +22,7 @@ fn mutable_borrow_of_pinned_projection() {
2122
}
2223

2324
fn move_of_pinned_projection() {
24-
let mut pair = (Foo, Foo);
25+
let mut pair = (Foo::default(), Foo::default());
2526

2627
{
2728
let _pin = &pin mut pair.0;
@@ -32,4 +33,28 @@ fn move_of_pinned_projection() {
3233
//~^ ERROR cannot move out of `pair.0` because it is pinned
3334
}
3435

36+
#[pin_v2]
37+
struct ContainsUnpinField {
38+
field: String,
39+
_pin: std::marker::PhantomPinned,
40+
}
41+
42+
fn pinned_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) {
43+
{
44+
let _ = &pin mut value;
45+
}
46+
47+
let _moved = value.field;
48+
//~^ ERROR cannot move out of `value.field` because it is pinned
49+
}
50+
51+
fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) {
52+
{
53+
let _ = &pin mut value;
54+
}
55+
56+
let _ = &mut value.field;
57+
//~^ ERROR cannot borrow `value.field` as mutable because it is pinned
58+
}
59+
3560
fn main() {}
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: cannot borrow `pair.0` as mutable because it is pinned
2-
--> $DIR/borrow-pinned-projection.rs:19:19
2+
--> $DIR/borrow-pinned-projection.rs:20:19
33
|
44
LL | let _pin = &pin mut pair.0;
55
| --------------- pin of `pair.0` occurs here
@@ -8,13 +8,31 @@ LL | let _borrow = &mut pair.0;
88
| ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here
99

1010
error: cannot move out of `pair.0` because it is pinned
11-
--> $DIR/borrow-pinned-projection.rs:31:18
11+
--> $DIR/borrow-pinned-projection.rs:32:18
1212
|
1313
LL | let _pin = &pin mut pair.0;
1414
| --------------- pin of `pair.0` occurs here
1515
...
1616
LL | let _moved = pair.0;
1717
| ^^^^^^ move out of `pair.0` occurs here
1818

19-
error: aborting due to 2 previous errors
19+
error: cannot move out of `value.field` because it is pinned
20+
--> $DIR/borrow-pinned-projection.rs:47:18
21+
|
22+
LL | let _ = &pin mut value;
23+
| -------------- pin of `value` occurs here
24+
...
25+
LL | let _moved = value.field;
26+
| ^^^^^^^^^^^ move out of `value.field` occurs here
27+
28+
error: cannot borrow `value.field` as mutable because it is pinned
29+
--> $DIR/borrow-pinned-projection.rs:56:13
30+
|
31+
LL | let _ = &pin mut value;
32+
| -------------- pin of `value` occurs here
33+
...
34+
LL | let _ = &mut value.field;
35+
| ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here
36+
37+
error: aborting due to 4 previous errors
2038

tests/ui/pin-ergonomics/borrow-unpin.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#![feature(pin_ergonomics)]
33
#![allow(dead_code, incomplete_features)]
44

5-
// This test ensures that the place cannot be mutably borrowed or moved after pinned
6-
// no matter if `place` is `Unpin` or not.
5+
// This test ensures `!Unpin` places cannot be mutably borrowed or moved after pinning.
6+
// `Unpin` places still obey ordinary borrow rules, but expired `&pin` borrows do not pin.
77

88
use std::marker::PhantomPinned;
99
use std::pin::Pin;
@@ -27,7 +27,7 @@ fn foo_move(_: Foo) {}
2727
fn immutable_pin_mut_then_move() {
2828
let mut foo = Foo::default();
2929
foo_pin_mut(&pin mut foo); // ok
30-
foo_move(foo); //~ ERROR cannot move out of `foo` because it is pinned
30+
foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is pinned
3131

3232
let mut foo = Foo::default();
3333
let x = &pin mut foo;
@@ -38,7 +38,7 @@ fn immutable_pin_mut_then_move() {
3838
fn pin_mut_then_move() {
3939
let mut foo = Foo::default();
4040
foo_pin_mut(&pin mut foo); // ok
41-
foo_move(foo); //~ ERROR cannot move out of `foo` because it is pinned
41+
foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is pinned
4242

4343
let mut foo = Foo::default();
4444
let x = &pin mut foo; // ok
@@ -49,7 +49,7 @@ fn pin_mut_then_move() {
4949
fn pin_ref_then_move() {
5050
let foo = Foo::default();
5151
foo_pin_ref(&pin const foo); // ok
52-
foo_move(foo); //~ ERROR cannot move out of `foo` because it is pinned
52+
foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is pinned
5353

5454
let foo = Foo::default();
5555
let x = &pin const foo; // ok

tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
error: cannot move out of `foo` because it is pinned
2-
--> $DIR/borrow-unpin.rs:30:14
3-
|
4-
LL | foo_pin_mut(&pin mut foo); // ok
5-
| ------------ pin of `foo` occurs here
6-
LL | foo_move(foo);
7-
| ^^^ move out of `foo` occurs here
8-
91
error[E0505]: cannot move out of `foo` because it is borrowed
102
--> $DIR/borrow-unpin.rs:34:14
113
|
@@ -27,14 +19,6 @@ LL | struct Foo;
2719
LL | let x = &pin mut foo;
2820
| --- you could clone this value
2921

30-
error: cannot move out of `foo` because it is pinned
31-
--> $DIR/borrow-unpin.rs:41:14
32-
|
33-
LL | foo_pin_mut(&pin mut foo); // ok
34-
| ------------ pin of `foo` occurs here
35-
LL | foo_move(foo);
36-
| ^^^ move out of `foo` occurs here
37-
3822
error[E0505]: cannot move out of `foo` because it is borrowed
3923
--> $DIR/borrow-unpin.rs:45:14
4024
|
@@ -56,14 +40,6 @@ LL | struct Foo;
5640
LL | let x = &pin mut foo; // ok
5741
| --- you could clone this value
5842

59-
error: cannot move out of `foo` because it is pinned
60-
--> $DIR/borrow-unpin.rs:52:14
61-
|
62-
LL | foo_pin_ref(&pin const foo); // ok
63-
| -------------- pin of `foo` occurs here
64-
LL | foo_move(foo);
65-
| ^^^ move out of `foo` occurs here
66-
6743
error[E0505]: cannot move out of `foo` because it is borrowed
6844
--> $DIR/borrow-unpin.rs:56:14
6945
|
@@ -125,7 +101,7 @@ LL | foo_pin_ref(&pin const foo);
125101
LL | foo_pin_mut(x);
126102
| - mutable borrow later used here
127103

128-
error: aborting due to 10 previous errors
104+
error: aborting due to 7 previous errors
129105

130106
Some errors have detailed explanations: E0499, E0502, E0505.
131107
For more information about an error, try `rustc --explain E0499`.

tests/ui/pin-ergonomics/borrow.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,24 @@
44
// Makes sure we can handle `&pin mut place` and `&pin const place` as sugar for
55
// `std::pin::pin!(place)` and `Pin::new(&place)`.
66

7+
use std::marker::PhantomPinned;
78
use std::pin::Pin;
89

910
#[pin_v2]
10-
struct Foo;
11+
#[derive(Default)]
12+
struct Foo(PhantomPinned);
1113

1214
fn foo_pin_mut(_: Pin<&mut Foo>) {}
1315

1416
fn foo_pin_ref(_: Pin<&Foo>) {}
1517

1618
fn bar() {
17-
let mut x: Pin<&mut _> = &pin mut Foo;
19+
let mut x: Pin<&mut _> = &pin mut Foo::default();
1820
foo_pin_mut(x.as_mut());
1921
foo_pin_mut(x.as_mut());
2022
foo_pin_ref(x);
2123

22-
let x: Pin<&_> = &pin const Foo;
24+
let x: Pin<&_> = &pin const Foo::default();
2325

2426
foo_pin_ref(x);
2527
foo_pin_ref(x);
@@ -32,7 +34,7 @@ fn baz(mut x: Foo, mut y: Foo) {
3234
let _x = &mut x; //~ ERROR cannot borrow `x` as mutable because it is pinned
3335
let _x = x; //~ ERROR cannot move out of `x` because it is pinned
3436

35-
x = Foo;
37+
x = Foo::default();
3638
let _x = &mut x; // ok
3739

3840
{

tests/ui/pin-ergonomics/borrow.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: cannot borrow `x` as mutable because it is pinned
2-
--> $DIR/borrow.rs:32:14
2+
--> $DIR/borrow.rs:34:14
33
|
44
LL | let _x = &pin mut x;
55
| ---------- pin of `x` occurs here
@@ -8,7 +8,7 @@ LL | let _x = &mut x;
88
| ^^^^^^ borrow of `x` as mutable occurs here
99

1010
error: cannot move out of `x` because it is pinned
11-
--> $DIR/borrow.rs:33:14
11+
--> $DIR/borrow.rs:35:14
1212
|
1313
LL | let _x = &pin mut x;
1414
| ---------- pin of `x` occurs here
@@ -17,7 +17,7 @@ LL | let _x = x;
1717
| ^ move out of `x` occurs here
1818

1919
error: cannot borrow `y` as mutable because it is pinned
20-
--> $DIR/borrow.rs:41:14
20+
--> $DIR/borrow.rs:43:14
2121
|
2222
LL | let _y = &pin const y;
2323
| ------------ pin of `y` occurs here
@@ -26,7 +26,7 @@ LL | let _y = &mut y;
2626
| ^^^^^^ borrow of `y` as mutable occurs here
2727

2828
error: cannot move out of `y` because it is pinned
29-
--> $DIR/borrow.rs:42:14
29+
--> $DIR/borrow.rs:44:14
3030
|
3131
LL | let _y = &pin const y;
3232
| ------------ pin of `y` occurs here

tests/ui/pin-ergonomics/direct-borrow-requires-pin-v2.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,28 @@ fn direct_pin_mut_drop_generic(mut input: DropGenericAdt<NotUnpin>) {
8080
//~^ ERROR cannot directly pin a type that is not structurally pinnable
8181
}
8282

83+
fn direct_pin_mut_unpin_then_mut_borrow_and_move() {
84+
let mut value = UnpinAdt;
85+
{
86+
let _ = &pin mut value;
87+
}
88+
let _ = &mut value;
89+
let _ = value;
90+
}
91+
92+
fn direct_pin_const_unpin_then_move() {
93+
let value = UnpinAdt;
94+
{
95+
let _ = &pin const value;
96+
}
97+
let _ = value;
98+
}
99+
100+
fn direct_pin_mut_generic_unpin_bound_then_move<T: Unpin>(mut value: T) {
101+
{
102+
let _ = &pin mut value;
103+
}
104+
let _ = value;
105+
}
106+
83107
fn main() {}

0 commit comments

Comments
 (0)