Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,10 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Pins<'_, 'tcx> {
if let mir::Rvalue::Ref(_, mir::BorrowKind::Pinned(_, kind), place) = rhs
&& matches!(*kind, mir::PinBorrowKind::Persistent)
{
self.gen_pins_on_place(state, *place);
let place_ty = place.ty(self.body, self.tcx).ty;
if !place_ty.is_unpin(self.tcx, self.body.typing_env(self.tcx)) {
self.gen_pins_on_place(state, *place);
}
}
}

Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1270,17 +1270,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
&self,
state: &'s BorrowckDomain,
) -> Option<&'s MixedBitSet<BorrowIndex>> {
// FIXME(pin_ergonomics): borrowck behaviors depend on a safe trait
// which should not contain any safety invariants.
// if place
// .ty(self.body, self.infcx.tcx)
// .ty
// .is_unpin(self.infcx.tcx, self.body.typing_env(self.infcx.tcx))
// {
// None
// } else {
Some(&state.pinned_borrows)
// }
}

#[instrument(level = "debug", skip(self, state))]
Expand Down
31 changes: 28 additions & 3 deletions tests/ui/pin-ergonomics/borrow-pinned-projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
// of `pair.0` until reassignment.

#[pin_v2]
struct Foo;
#[derive(Default)]
struct Foo(std::marker::PhantomPinned);

fn mutable_borrow_of_pinned_projection() {
let mut pair = (Foo, Foo);
let mut pair = (Foo::default(), Foo::default());

{
let _pin = &pin mut pair.0;
Expand All @@ -21,7 +22,7 @@ fn mutable_borrow_of_pinned_projection() {
}

fn move_of_pinned_projection() {
let mut pair = (Foo, Foo);
let mut pair = (Foo::default(), Foo::default());

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

#[pin_v2]
struct ContainsUnpinField {
field: String,
_pin: std::marker::PhantomPinned,
}

fn pinned_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) {
{
let _ = &pin mut value;
}

let _moved = value.field;
//~^ ERROR cannot move out of `value.field` because it is pinned
}

fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) {
{
let _ = &pin mut value;
}

let _ = &mut value.field;
//~^ ERROR cannot borrow `value.field` as mutable because it is pinned
}

fn main() {}
24 changes: 21 additions & 3 deletions tests/ui/pin-ergonomics/borrow-pinned-projection.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: cannot borrow `pair.0` as mutable because it is pinned
--> $DIR/borrow-pinned-projection.rs:19:19
--> $DIR/borrow-pinned-projection.rs:20:19
|
LL | let _pin = &pin mut pair.0;
| --------------- pin of `pair.0` occurs here
Expand All @@ -8,13 +8,31 @@ LL | let _borrow = &mut pair.0;
| ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here

error: cannot move out of `pair.0` because it is pinned
--> $DIR/borrow-pinned-projection.rs:31:18
--> $DIR/borrow-pinned-projection.rs:32:18
|
LL | let _pin = &pin mut pair.0;
| --------------- pin of `pair.0` occurs here
...
LL | let _moved = pair.0;
| ^^^^^^ move out of `pair.0` occurs here

error: aborting due to 2 previous errors
error: cannot move out of `value.field` because it is pinned
--> $DIR/borrow-pinned-projection.rs:47:18
|
LL | let _ = &pin mut value;
| -------------- pin of `value` occurs here
...
LL | let _moved = value.field;
| ^^^^^^^^^^^ move out of `value.field` occurs here

error: cannot borrow `value.field` as mutable because it is pinned
--> $DIR/borrow-pinned-projection.rs:56:13
|
LL | let _ = &pin mut value;
| -------------- pin of `value` occurs here
...
LL | let _ = &mut value.field;
| ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here

error: aborting due to 4 previous errors

10 changes: 5 additions & 5 deletions tests/ui/pin-ergonomics/borrow-unpin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]

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

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

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

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

let foo = Foo::default();
let x = &pin const foo; // ok
Expand Down
26 changes: 1 addition & 25 deletions tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
error: cannot move out of `foo` because it is pinned
--> $DIR/borrow-unpin.rs:30:14
|
LL | foo_pin_mut(&pin mut foo); // ok
| ------------ pin of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here

error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:34:14
|
Expand All @@ -27,14 +19,6 @@ LL | struct Foo;
LL | let x = &pin mut foo;
| --- you could clone this value

error: cannot move out of `foo` because it is pinned
--> $DIR/borrow-unpin.rs:41:14
|
LL | foo_pin_mut(&pin mut foo); // ok
| ------------ pin of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here

error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:45:14
|
Expand All @@ -56,14 +40,6 @@ LL | struct Foo;
LL | let x = &pin mut foo; // ok
| --- you could clone this value

error: cannot move out of `foo` because it is pinned
--> $DIR/borrow-unpin.rs:52:14
|
LL | foo_pin_ref(&pin const foo); // ok
| -------------- pin of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here

error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:56:14
|
Expand Down Expand Up @@ -125,7 +101,7 @@ LL | foo_pin_ref(&pin const foo);
LL | foo_pin_mut(x);
| - mutable borrow later used here

error: aborting due to 10 previous errors
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0499, E0502, E0505.
For more information about an error, try `rustc --explain E0499`.
10 changes: 6 additions & 4 deletions tests/ui/pin-ergonomics/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@
// Makes sure we can handle `&pin mut place` and `&pin const place` as sugar for
// `std::pin::pin!(place)` and `Pin::new(&place)`.

use std::marker::PhantomPinned;
use std::pin::Pin;

#[pin_v2]
struct Foo;
#[derive(Default)]
struct Foo(PhantomPinned);

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

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

fn bar() {
let mut x: Pin<&mut _> = &pin mut Foo;
let mut x: Pin<&mut _> = &pin mut Foo::default();
foo_pin_mut(x.as_mut());
foo_pin_mut(x.as_mut());
foo_pin_ref(x);

let x: Pin<&_> = &pin const Foo;
let x: Pin<&_> = &pin const Foo::default();

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

x = Foo;
x = Foo::default();
let _x = &mut x; // ok

{
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/pin-ergonomics/borrow.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: cannot borrow `x` as mutable because it is pinned
--> $DIR/borrow.rs:32:14
--> $DIR/borrow.rs:34:14
|
LL | let _x = &pin mut x;
| ---------- pin of `x` occurs here
Expand All @@ -8,7 +8,7 @@ LL | let _x = &mut x;
| ^^^^^^ borrow of `x` as mutable occurs here

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

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

error: cannot move out of `y` because it is pinned
--> $DIR/borrow.rs:42:14
--> $DIR/borrow.rs:44:14
|
LL | let _y = &pin const y;
| ------------ pin of `y` occurs here
Expand Down
24 changes: 24 additions & 0 deletions tests/ui/pin-ergonomics/direct-borrow-requires-pin-v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,28 @@ fn direct_pin_mut_drop_generic(mut input: DropGenericAdt<NotUnpin>) {
//~^ ERROR cannot directly pin a type that is not structurally pinnable
}

fn direct_pin_mut_unpin_then_mut_borrow_and_move() {
let mut value = UnpinAdt;
{
let _ = &pin mut value;
}
let _ = &mut value;
let _ = value;
}

fn direct_pin_const_unpin_then_move() {
let value = UnpinAdt;
{
let _ = &pin const value;
}
let _ = value;
}

fn direct_pin_mut_generic_unpin_bound_then_move<T: Unpin>(mut value: T) {
{
let _ = &pin mut value;
}
let _ = value;
}

fn main() {}
Loading