Skip to content

Commit d7f4bbd

Browse files
P8L1frank-king
authored andcommitted
Require pin_v2 for direct pin borrows of ADTs
1 parent 122d1be commit d7f4bbd

12 files changed

Lines changed: 123 additions & 32 deletions

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,21 @@ pub(crate) struct ProjectOnNonPinProjectType {
13851385
pub sugg_span: Option<Span>,
13861386
}
13871387

1388+
#[derive(Diagnostic)]
1389+
#[diag("cannot directly pin an ADT that is not `#[pin_v2]`")]
1390+
pub(crate) struct DirectPinBorrowOfNonPinProjectType {
1391+
#[primary_span]
1392+
pub span: Span,
1393+
#[note("type defined here")]
1394+
pub def_span: Option<Span>,
1395+
#[suggestion(
1396+
"add `#[pin_v2]` here",
1397+
code = "#[pin_v2]\n",
1398+
applicability = "machine-applicable"
1399+
)]
1400+
pub sugg_span: Option<Span>,
1401+
}
1402+
13881403
#[derive(Diagnostic)]
13891404
#[diag("falling back to `f32` as the trait bound `f32: From<f64>` is not satisfied")]
13901405
pub(crate) struct FloatLiteralF32Fallback {

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
499499
Ty::new_ptr(self.tcx, ty, mutbl)
500500
}
501501
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
502+
if kind == hir::BorrowKind::Pin {
503+
self.check_pin_borrow_of_adt_requires_pin_v2(ty, expr.span);
504+
}
505+
502506
// Note: at this point, we cannot say what the best lifetime
503507
// is to use for resulting pointer. We want to use the
504508
// shortest lifetime possible so as to avoid spurious borrowck
@@ -523,6 +527,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523527
}
524528
}
525529

530+
fn check_pin_borrow_of_adt_requires_pin_v2(&self, ty: Ty<'tcx>, span: Span) {
531+
let ty = self.structurally_resolve_type(span, ty);
532+
if let Some(adt) = ty.ty_adt_def()
533+
&& !adt.is_pin_project()
534+
{
535+
let def_span = self.tcx.hir_span_if_local(adt.did());
536+
let sugg_span = def_span.map(|span| span.shrink_to_lo());
537+
self.dcx().emit_err(crate::errors::DirectPinBorrowOfNonPinProjectType {
538+
span,
539+
def_span,
540+
sugg_span,
541+
});
542+
}
543+
}
544+
526545
/// Does this expression refer to a place that either:
527546
/// * Is based on a local or static.
528547
/// * Contains a dereference

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// unrelated disjoint fields, but it must reject later mutable borrows or moves
66
// of `pair.0` until reassignment.
77

8+
#[pin_v2]
89
struct Foo;
910

1011
fn mutable_borrow_of_pinned_projection() {

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

Lines changed: 2 additions & 2 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:18:19
2+
--> $DIR/borrow-pinned-projection.rs:19:19
33
|
44
LL | let _pin = &pin mut pair.0;
55
| --------------- pin of `pair.0` occurs here
@@ -8,7 +8,7 @@ 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:30:18
11+
--> $DIR/borrow-pinned-projection.rs:31:18
1212
|
1313
LL | let _pin = &pin mut pair.0;
1414
| --------------- pin of `pair.0` occurs here

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: cannot move out of `foo` because it is pinned
2-
--> $DIR/borrow-unpin.rs:28:14
2+
--> $DIR/borrow-unpin.rs:30:14
33
|
44
LL | foo_pin_mut(&pin mut foo); // ok
55
| ------------ pin of `foo` occurs here
66
LL | foo_move(foo);
77
| ^^^ move out of `foo` occurs here
88

99
error[E0505]: cannot move out of `foo` because it is borrowed
10-
--> $DIR/borrow-unpin.rs:32:14
10+
--> $DIR/borrow-unpin.rs:34:14
1111
|
1212
LL | let mut foo = Foo::default();
1313
| ------- binding `foo` declared here
@@ -19,7 +19,7 @@ LL | foo_pin_mut(x); // ok
1919
| - borrow later used here
2020
|
2121
note: if `Foo` implemented `Clone`, you could clone the value
22-
--> $DIR/borrow-unpin.rs:13:1
22+
--> $DIR/borrow-unpin.rs:14:1
2323
|
2424
LL | struct Foo(PhantomPinned);
2525
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -28,15 +28,15 @@ LL | let x = &pin mut foo;
2828
| --- you could clone this value
2929

3030
error: cannot move out of `foo` because it is pinned
31-
--> $DIR/borrow-unpin.rs:39:14
31+
--> $DIR/borrow-unpin.rs:41:14
3232
|
3333
LL | foo_pin_mut(&pin mut foo); // ok
3434
| ------------ pin of `foo` occurs here
3535
LL | foo_move(foo);
3636
| ^^^ move out of `foo` occurs here
3737

3838
error[E0505]: cannot move out of `foo` because it is borrowed
39-
--> $DIR/borrow-unpin.rs:43:14
39+
--> $DIR/borrow-unpin.rs:45:14
4040
|
4141
LL | let mut foo = Foo::default();
4242
| ------- binding `foo` declared here
@@ -48,7 +48,7 @@ LL | foo_pin_mut(x); // ok
4848
| - borrow later used here
4949
|
5050
note: if `Foo` implemented `Clone`, you could clone the value
51-
--> $DIR/borrow-unpin.rs:13:1
51+
--> $DIR/borrow-unpin.rs:14:1
5252
|
5353
LL | struct Foo(PhantomPinned);
5454
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -57,15 +57,15 @@ LL | let x = &pin mut foo; // ok
5757
| --- you could clone this value
5858

5959
error: cannot move out of `foo` because it is pinned
60-
--> $DIR/borrow-unpin.rs:50:14
60+
--> $DIR/borrow-unpin.rs:52:14
6161
|
6262
LL | foo_pin_ref(&pin const foo); // ok
6363
| -------------- pin of `foo` occurs here
6464
LL | foo_move(foo);
6565
| ^^^ move out of `foo` occurs here
6666

6767
error[E0505]: cannot move out of `foo` because it is borrowed
68-
--> $DIR/borrow-unpin.rs:54:14
68+
--> $DIR/borrow-unpin.rs:56:14
6969
|
7070
LL | let foo = Foo::default();
7171
| --- binding `foo` declared here
@@ -77,7 +77,7 @@ LL | foo_pin_ref(x);
7777
| - borrow later used here
7878
|
7979
note: if `Foo` implemented `Clone`, you could clone the value
80-
--> $DIR/borrow-unpin.rs:13:1
80+
--> $DIR/borrow-unpin.rs:14:1
8181
|
8282
LL | struct Foo(PhantomPinned);
8383
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -86,7 +86,7 @@ LL | let x = &pin const foo; // ok
8686
| --- you could clone this value
8787

8888
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
89-
--> $DIR/borrow-unpin.rs:65:13
89+
--> $DIR/borrow-unpin.rs:67:13
9090
|
9191
LL | let x = &pin mut foo; // ok
9292
| ------------ mutable borrow occurs here
@@ -96,7 +96,7 @@ LL | foo_pin_mut(x);
9696
| - mutable borrow later used here
9797

9898
error[E0499]: cannot borrow `foo` as mutable more than once at a time
99-
--> $DIR/borrow-unpin.rs:87:17
99+
--> $DIR/borrow-unpin.rs:89:17
100100
|
101101
LL | let x = &pin mut foo; // ok
102102
| ------------ first mutable borrow occurs here
@@ -106,7 +106,7 @@ LL | foo_pin_mut(x);
106106
| - first borrow later used here
107107

108108
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
109-
--> $DIR/borrow-unpin.rs:98:17
109+
--> $DIR/borrow-unpin.rs:100:17
110110
|
111111
LL | let x = &pin const foo; // ok
112112
| -------------- immutable borrow occurs here
@@ -116,7 +116,7 @@ LL | foo_pin_ref(x);
116116
| - immutable borrow later used here
117117

118118
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
119-
--> $DIR/borrow-unpin.rs:109:17
119+
--> $DIR/borrow-unpin.rs:111:17
120120
|
121121
LL | let x = &pin mut foo; // ok
122122
| ------------ mutable borrow occurs here

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ use std::marker::PhantomPinned;
99
use std::pin::Pin;
1010

1111
#[cfg(pinned)]
12+
#[pin_v2]
1213
#[derive(Default)]
1314
struct Foo(PhantomPinned);
1415

1516
#[cfg(unpin)]
17+
#[pin_v2]
1618
#[derive(Default)]
1719
struct Foo;
1820

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: cannot move out of `foo` because it is pinned
2-
--> $DIR/borrow-unpin.rs:28:14
2+
--> $DIR/borrow-unpin.rs:30:14
33
|
44
LL | foo_pin_mut(&pin mut foo); // ok
55
| ------------ pin of `foo` occurs here
66
LL | foo_move(foo);
77
| ^^^ move out of `foo` occurs here
88

99
error[E0505]: cannot move out of `foo` because it is borrowed
10-
--> $DIR/borrow-unpin.rs:32:14
10+
--> $DIR/borrow-unpin.rs:34:14
1111
|
1212
LL | let mut foo = Foo::default();
1313
| ------- binding `foo` declared here
@@ -19,7 +19,7 @@ LL | foo_pin_mut(x); // ok
1919
| - borrow later used here
2020
|
2121
note: if `Foo` implemented `Clone`, you could clone the value
22-
--> $DIR/borrow-unpin.rs:17:1
22+
--> $DIR/borrow-unpin.rs:19:1
2323
|
2424
LL | struct Foo;
2525
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -28,15 +28,15 @@ LL | let x = &pin mut foo;
2828
| --- you could clone this value
2929

3030
error: cannot move out of `foo` because it is pinned
31-
--> $DIR/borrow-unpin.rs:39:14
31+
--> $DIR/borrow-unpin.rs:41:14
3232
|
3333
LL | foo_pin_mut(&pin mut foo); // ok
3434
| ------------ pin of `foo` occurs here
3535
LL | foo_move(foo);
3636
| ^^^ move out of `foo` occurs here
3737

3838
error[E0505]: cannot move out of `foo` because it is borrowed
39-
--> $DIR/borrow-unpin.rs:43:14
39+
--> $DIR/borrow-unpin.rs:45:14
4040
|
4141
LL | let mut foo = Foo::default();
4242
| ------- binding `foo` declared here
@@ -48,7 +48,7 @@ LL | foo_pin_mut(x); // ok
4848
| - borrow later used here
4949
|
5050
note: if `Foo` implemented `Clone`, you could clone the value
51-
--> $DIR/borrow-unpin.rs:17:1
51+
--> $DIR/borrow-unpin.rs:19:1
5252
|
5353
LL | struct Foo;
5454
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -57,15 +57,15 @@ LL | let x = &pin mut foo; // ok
5757
| --- you could clone this value
5858

5959
error: cannot move out of `foo` because it is pinned
60-
--> $DIR/borrow-unpin.rs:50:14
60+
--> $DIR/borrow-unpin.rs:52:14
6161
|
6262
LL | foo_pin_ref(&pin const foo); // ok
6363
| -------------- pin of `foo` occurs here
6464
LL | foo_move(foo);
6565
| ^^^ move out of `foo` occurs here
6666

6767
error[E0505]: cannot move out of `foo` because it is borrowed
68-
--> $DIR/borrow-unpin.rs:54:14
68+
--> $DIR/borrow-unpin.rs:56:14
6969
|
7070
LL | let foo = Foo::default();
7171
| --- binding `foo` declared here
@@ -77,7 +77,7 @@ LL | foo_pin_ref(x);
7777
| - borrow later used here
7878
|
7979
note: if `Foo` implemented `Clone`, you could clone the value
80-
--> $DIR/borrow-unpin.rs:17:1
80+
--> $DIR/borrow-unpin.rs:19:1
8181
|
8282
LL | struct Foo;
8383
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -86,7 +86,7 @@ LL | let x = &pin const foo; // ok
8686
| --- you could clone this value
8787

8888
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
89-
--> $DIR/borrow-unpin.rs:65:13
89+
--> $DIR/borrow-unpin.rs:67:13
9090
|
9191
LL | let x = &pin mut foo; // ok
9292
| ------------ mutable borrow occurs here
@@ -96,7 +96,7 @@ LL | foo_pin_mut(x);
9696
| - mutable borrow later used here
9797

9898
error[E0499]: cannot borrow `foo` as mutable more than once at a time
99-
--> $DIR/borrow-unpin.rs:87:17
99+
--> $DIR/borrow-unpin.rs:89:17
100100
|
101101
LL | let x = &pin mut foo; // ok
102102
| ------------ first mutable borrow occurs here
@@ -106,7 +106,7 @@ LL | foo_pin_mut(x);
106106
| - first borrow later used here
107107

108108
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
109-
--> $DIR/borrow-unpin.rs:98:17
109+
--> $DIR/borrow-unpin.rs:100:17
110110
|
111111
LL | let x = &pin const foo; // ok
112112
| -------------- immutable borrow occurs here
@@ -116,7 +116,7 @@ LL | foo_pin_ref(x);
116116
| - immutable borrow later used here
117117

118118
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
119-
--> $DIR/borrow-unpin.rs:109:17
119+
--> $DIR/borrow-unpin.rs:111:17
120120
|
121121
LL | let x = &pin mut foo; // ok
122122
| ------------ mutable borrow occurs here

tests/ui/pin-ergonomics/borrow.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use std::pin::Pin;
88

9+
#[pin_v2]
910
struct Foo;
1011

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

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:31:14
2+
--> $DIR/borrow.rs:32: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:32:14
11+
--> $DIR/borrow.rs:33: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:40:14
20+
--> $DIR/borrow.rs:41: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:41:14
29+
--> $DIR/borrow.rs:42:14
3030
|
3131
LL | let _y = &pin const y;
3232
| ------------ pin of `y` occurs here
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(pin_ergonomics)]
2+
#![allow(incomplete_features)]
3+
//@ normalize-stderr: "\n\n\z" -> "\n"
4+
5+
struct NotPinV2;
6+
7+
fn direct_pin_mut(mut value: NotPinV2) {
8+
let _ = &pin mut value;
9+
//~^ ERROR cannot directly pin an ADT that is not `#[pin_v2]`
10+
}
11+
12+
fn direct_pin_const(value: NotPinV2) {
13+
let _ = &pin const value;
14+
//~^ ERROR cannot directly pin an ADT that is not `#[pin_v2]`
15+
}
16+
17+
fn main() {}

0 commit comments

Comments
 (0)