Skip to content

Commit 9fe2f02

Browse files
P8L1frank-king
authored andcommitted
Handle ref pin patterns in borrowck
1 parent 3d4d351 commit 9fe2f02

10 files changed

Lines changed: 200 additions & 24 deletions

File tree

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,8 +2694,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
26942694
ScheduleDrops::Yes,
26952695
);
26962696

2697-
let rvalue =
2698-
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
2697+
let rvalue = Rvalue::Ref(
2698+
re_erased,
2699+
util::ref_pat_borrow_kind(pinnedness, mutbl),
2700+
binding.source,
2701+
);
26992702
let rvalue = match pinnedness {
27002703
ty::Pinnedness::Not => rvalue,
27012704
ty::Pinnedness::Pinned => {
@@ -2741,8 +2744,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
27412744
Rvalue::Use(self.consume_by_copy_or_move(binding.source), WithRetag::Yes)
27422745
}
27432746
ByRef::Yes(pinnedness, mutbl) => {
2744-
let rvalue =
2745-
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
2747+
let rvalue = Rvalue::Ref(
2748+
re_erased,
2749+
util::ref_pat_borrow_kind(pinnedness, mutbl),
2750+
binding.source,
2751+
);
27462752
match pinnedness {
27472753
ty::Pinnedness::Not => rvalue,
27482754
ty::Pinnedness::Pinned => {

compiler/rustc_mir_build/src/builder/matches/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
344344
Mutability::Not => (LangItem::Deref, sym::deref),
345345
Mutability::Mut => (LangItem::DerefMut, sym::deref_mut),
346346
};
347-
let borrow_kind = super::util::ref_pat_borrow_kind(mutability);
347+
let borrow_kind = super::util::ref_pat_borrow_kind(ty::Pinnedness::Not, mutability);
348348
let source_info = self.source_info(span);
349349
let re_erased = self.tcx.lifetimes.re_erased;
350350
let trait_item = self.tcx.require_lang_item(trait_item, span);

compiler/rustc_mir_build/src/builder/matches/util.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_data_structures::fx::FxIndexMap;
22
use rustc_middle::mir::*;
3-
use rustc_middle::ty::Ty;
3+
use rustc_middle::ty::{self, Ty};
44
use rustc_span::Span;
55
use tracing::debug;
66

@@ -228,9 +228,15 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
228228
}
229229

230230
#[must_use]
231-
pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
232-
match ref_mutability {
233-
Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
234-
Mutability::Not => BorrowKind::Shared,
231+
pub(crate) fn ref_pat_borrow_kind(
232+
pinnedness: ty::Pinnedness,
233+
ref_mutability: Mutability,
234+
) -> BorrowKind {
235+
match pinnedness {
236+
ty::Pinnedness::Pinned => BorrowKind::Pinned(ref_mutability, PinBorrowKind::Persistent),
237+
ty::Pinnedness::Not => match ref_mutability {
238+
Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
239+
Mutability::Not => BorrowKind::Shared,
240+
},
235241
}
236242
}

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ fn mutable_borrow_of_pinned_projection() {
2121
//~^ ERROR cannot borrow `pair.0` as mutable because it is pinned
2222
}
2323

24+
fn ref_pin_pattern_mutable_borrow_of_pinned_projection() {
25+
let mut pair = (Foo::default(), Foo::default());
26+
27+
{
28+
let ref pin mut _pin = pair.0;
29+
}
30+
31+
let _other = &mut pair.1;
32+
let _borrow = &mut pair.0;
33+
//~^ ERROR cannot borrow `pair.0` as mutable because it is pinned
34+
}
35+
2436
fn move_of_pinned_projection() {
2537
let mut pair = (Foo::default(), Foo::default());
2638

@@ -33,6 +45,18 @@ fn move_of_pinned_projection() {
3345
//~^ ERROR cannot move out of `pair.0` because it is pinned
3446
}
3547

48+
fn ref_pin_pattern_move_of_pinned_projection() {
49+
let mut pair = (Foo::default(), Foo::default());
50+
51+
{
52+
let ref pin mut _pin = pair.0;
53+
}
54+
55+
let _other = &mut pair.1;
56+
let _moved = pair.0;
57+
//~^ ERROR cannot move out of `pair.0` because it is pinned
58+
}
59+
3660
#[pin_v2]
3761
struct ContainsUnpinField {
3862
field: String,
@@ -48,6 +72,15 @@ fn pinned_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) {
4872
//~^ ERROR cannot move out of `value.field` because it is pinned
4973
}
5074

75+
fn ref_pin_pattern_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) {
76+
{
77+
let ref pin mut _pin = value;
78+
}
79+
80+
let _moved = value.field;
81+
//~^ ERROR cannot move out of `value.field` because it is pinned
82+
}
83+
5184
fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) {
5285
{
5386
let _ = &pin mut value;
@@ -57,4 +90,13 @@ fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinFie
5790
//~^ ERROR cannot borrow `value.field` as mutable because it is pinned
5891
}
5992

93+
fn ref_pin_pattern_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) {
94+
{
95+
let ref pin mut _pin = value;
96+
}
97+
98+
let _ = &mut value.field;
99+
//~^ ERROR cannot borrow `value.field` as mutable because it is pinned
100+
}
101+
60102
fn main() {}

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

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,68 @@ LL | let _pin = &pin mut pair.0;
77
LL | let _borrow = &mut pair.0;
88
| ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here
99

10+
error: cannot borrow `pair.0` as mutable because it is pinned
11+
--> $DIR/borrow-pinned-projection.rs:32:19
12+
|
13+
LL | let ref pin mut _pin = pair.0;
14+
| ---------------- pin of `pair.0` occurs here
15+
...
16+
LL | let _borrow = &mut pair.0;
17+
| ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here
18+
1019
error: cannot move out of `pair.0` because it is pinned
11-
--> $DIR/borrow-pinned-projection.rs:32:18
20+
--> $DIR/borrow-pinned-projection.rs:44:18
1221
|
1322
LL | let _pin = &pin mut pair.0;
1423
| --------------- pin of `pair.0` occurs here
1524
...
1625
LL | let _moved = pair.0;
1726
| ^^^^^^ move out of `pair.0` occurs here
1827

28+
error: cannot move out of `pair.0` because it is pinned
29+
--> $DIR/borrow-pinned-projection.rs:56:18
30+
|
31+
LL | let ref pin mut _pin = pair.0;
32+
| ---------------- pin of `pair.0` occurs here
33+
...
34+
LL | let _moved = pair.0;
35+
| ^^^^^^ move out of `pair.0` occurs here
36+
1937
error: cannot move out of `value.field` because it is pinned
20-
--> $DIR/borrow-pinned-projection.rs:47:18
38+
--> $DIR/borrow-pinned-projection.rs:71:18
2139
|
2240
LL | let _ = &pin mut value;
2341
| -------------- pin of `value` occurs here
2442
...
2543
LL | let _moved = value.field;
2644
| ^^^^^^^^^^^ move out of `value.field` occurs here
2745

46+
error: cannot move out of `value.field` because it is pinned
47+
--> $DIR/borrow-pinned-projection.rs:80:18
48+
|
49+
LL | let ref pin mut _pin = value;
50+
| ---------------- pin of `value` occurs here
51+
...
52+
LL | let _moved = value.field;
53+
| ^^^^^^^^^^^ move out of `value.field` occurs here
54+
2855
error: cannot borrow `value.field` as mutable because it is pinned
29-
--> $DIR/borrow-pinned-projection.rs:56:13
56+
--> $DIR/borrow-pinned-projection.rs:89:13
3057
|
3158
LL | let _ = &pin mut value;
3259
| -------------- pin of `value` occurs here
3360
...
3461
LL | let _ = &mut value.field;
3562
| ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here
3663

37-
error: aborting due to 4 previous errors
64+
error: cannot borrow `value.field` as mutable because it is pinned
65+
--> $DIR/borrow-pinned-projection.rs:98:13
66+
|
67+
LL | let ref pin mut _pin = value;
68+
| ---------------- pin of `value` occurs here
69+
...
70+
LL | let _ = &mut value.field;
71+
| ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here
72+
73+
error: aborting due to 8 previous errors
3874

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,26 @@ LL | struct Foo(PhantomPinned);
8585
LL | let x = &pin const foo; // ok
8686
| --- you could clone this value
8787

88+
error: cannot move out of `foo` because it is pinned
89+
--> $DIR/borrow-unpin.rs:65:14
90+
|
91+
LL | let ref pin mut _x = foo;
92+
| -------------- pin of `foo` occurs here
93+
LL | }
94+
LL | foo_move(foo);
95+
| ^^^ move out of `foo` occurs here
96+
97+
error: cannot borrow `foo` as mutable because it is pinned
98+
--> $DIR/borrow-unpin.rs:73:13
99+
|
100+
LL | let ref pin mut _x = foo;
101+
| -------------- pin of `foo` occurs here
102+
LL | }
103+
LL | foo_mut(&mut foo);
104+
| ^^^^^^^^ borrow of `foo` as mutable occurs here
105+
88106
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
89-
--> $DIR/borrow-unpin.rs:67:13
107+
--> $DIR/borrow-unpin.rs:83:13
90108
|
91109
LL | let x = &pin mut foo; // ok
92110
| ------------ mutable borrow occurs here
@@ -96,7 +114,7 @@ LL | foo_pin_mut(x);
96114
| - mutable borrow later used here
97115

98116
error[E0499]: cannot borrow `foo` as mutable more than once at a time
99-
--> $DIR/borrow-unpin.rs:89:17
117+
--> $DIR/borrow-unpin.rs:105:17
100118
|
101119
LL | let x = &pin mut foo; // ok
102120
| ------------ first mutable borrow occurs here
@@ -106,7 +124,7 @@ LL | foo_pin_mut(x);
106124
| - first borrow later used here
107125

108126
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
109-
--> $DIR/borrow-unpin.rs:100:17
127+
--> $DIR/borrow-unpin.rs:116:17
110128
|
111129
LL | let x = &pin const foo; // ok
112130
| -------------- immutable borrow occurs here
@@ -116,7 +134,7 @@ LL | foo_pin_ref(x);
116134
| - immutable borrow later used here
117135

118136
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
119-
--> $DIR/borrow-unpin.rs:111:17
137+
--> $DIR/borrow-unpin.rs:127:17
120138
|
121139
LL | let x = &pin mut foo; // ok
122140
| ------------ mutable borrow occurs here
@@ -125,7 +143,7 @@ LL | foo_pin_ref(&pin const foo);
125143
LL | foo_pin_mut(x);
126144
| - mutable borrow later used here
127145

128-
error: aborting due to 10 previous errors
146+
error: aborting due to 12 previous errors
129147

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

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@ fn pin_ref_then_move() {
5757
foo_pin_ref(x);
5858
}
5959

60+
fn ref_pin_mut_then_move() {
61+
let mut foo = Foo::default();
62+
{
63+
let ref pin mut _x = foo;
64+
}
65+
foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is pinned
66+
}
67+
68+
fn ref_pin_mut_then_mut_borrow() {
69+
let mut foo = Foo::default();
70+
{
71+
let ref pin mut _x = foo;
72+
}
73+
foo_mut(&mut foo); //[pinned]~ ERROR cannot borrow `foo` as mutable because it is pinned
74+
}
75+
6076
fn pin_mut_then_ref() {
6177
let mut foo = Foo::default();
6278
foo_pin_mut(&pin mut foo); // ok

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ LL | let x = &pin const foo; // ok
6262
| --- you could clone this value
6363

6464
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
65-
--> $DIR/borrow-unpin.rs:67:13
65+
--> $DIR/borrow-unpin.rs:83:13
6666
|
6767
LL | let x = &pin mut foo; // ok
6868
| ------------ mutable borrow occurs here
@@ -72,7 +72,7 @@ LL | foo_pin_mut(x);
7272
| - mutable borrow later used here
7373

7474
error[E0499]: cannot borrow `foo` as mutable more than once at a time
75-
--> $DIR/borrow-unpin.rs:89:17
75+
--> $DIR/borrow-unpin.rs:105:17
7676
|
7777
LL | let x = &pin mut foo; // ok
7878
| ------------ first mutable borrow occurs here
@@ -82,7 +82,7 @@ LL | foo_pin_mut(x);
8282
| - first borrow later used here
8383

8484
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
85-
--> $DIR/borrow-unpin.rs:100:17
85+
--> $DIR/borrow-unpin.rs:116:17
8686
|
8787
LL | let x = &pin const foo; // ok
8888
| -------------- immutable borrow occurs here
@@ -92,7 +92,7 @@ LL | foo_pin_ref(x);
9292
| - immutable borrow later used here
9393

9494
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
95-
--> $DIR/borrow-unpin.rs:111:17
95+
--> $DIR/borrow-unpin.rs:127:17
9696
|
9797
LL | let x = &pin mut foo; // ok
9898
| ------------ mutable borrow occurs here

tests/ui/pin-ergonomics/borrow.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,20 @@ fn baz(mut x: Foo, mut y: Foo) {
4444
let _y = y; //~ ERROR cannot move out of `y` because it is pinned
4545
}
4646

47+
fn ref_pin_mut_then_mut_borrow_and_move(mut x: Foo) {
48+
{
49+
let ref pin mut _x = x;
50+
}
51+
let _x = &mut x; //~ ERROR cannot borrow `x` as mutable because it is pinned
52+
let _x = x; //~ ERROR cannot move out of `x` because it is pinned
53+
}
54+
55+
fn ref_pin_const_then_mut_borrow_and_move(mut y: Foo) {
56+
{
57+
let ref pin const _y = y;
58+
}
59+
let _y = &mut y; //~ ERROR cannot borrow `y` as mutable because it is pinned
60+
let _y = y; //~ ERROR cannot move out of `y` because it is pinned
61+
}
62+
4763
fn main() {}

tests/ui/pin-ergonomics/borrow.stderr

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,41 @@ LL | let _y = &pin const y;
3434
LL | let _y = y;
3535
| ^ move out of `y` occurs here
3636

37-
error: aborting due to 4 previous errors
37+
error: cannot borrow `x` as mutable because it is pinned
38+
--> $DIR/borrow.rs:51:14
39+
|
40+
LL | let ref pin mut _x = x;
41+
| -------------- pin of `x` occurs here
42+
LL | }
43+
LL | let _x = &mut x;
44+
| ^^^^^^ borrow of `x` as mutable occurs here
45+
46+
error: cannot move out of `x` because it is pinned
47+
--> $DIR/borrow.rs:52:14
48+
|
49+
LL | let ref pin mut _x = x;
50+
| -------------- pin of `x` occurs here
51+
...
52+
LL | let _x = x;
53+
| ^ move out of `x` occurs here
54+
55+
error: cannot borrow `y` as mutable because it is pinned
56+
--> $DIR/borrow.rs:59:14
57+
|
58+
LL | let ref pin const _y = y;
59+
| ---------------- pin of `y` occurs here
60+
LL | }
61+
LL | let _y = &mut y;
62+
| ^^^^^^ borrow of `y` as mutable occurs here
63+
64+
error: cannot move out of `y` because it is pinned
65+
--> $DIR/borrow.rs:60:14
66+
|
67+
LL | let ref pin const _y = y;
68+
| ---------------- pin of `y` occurs here
69+
...
70+
LL | let _y = y;
71+
| ^ move out of `y` occurs here
72+
73+
error: aborting due to 8 previous errors
3874

0 commit comments

Comments
 (0)