Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
24 changes: 3 additions & 21 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1266,23 +1266,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
}
}

fn pinned_borrows<'s>(
&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))]
fn check_access_for_conflict(
&mut self,
Expand All @@ -1295,7 +1278,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
let mut error_reported = false;

let borrows_in_scope = self.borrows_in_scope(location, state);
let pinned_borrows = self.pinned_borrows(state);
let pinned_borrows = &state.pinned_borrows;

each_borrow_involving_path(
self,
Expand All @@ -1304,8 +1287,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
(sd, place_span.0),
self.borrow_set,
|borrow_index| {
borrows_in_scope.contains(borrow_index)
|| pinned_borrows.is_some_and(|p| p.contains(borrow_index))
borrows_in_scope.contains(borrow_index) || pinned_borrows.contains(borrow_index)
},
|this, borrow_index, borrow| match (rw, borrow.kind) {
// Obviously an activation is compatible with its own
Expand Down Expand Up @@ -1388,7 +1370,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
if !borrows_in_scope.contains(borrow_index) =>
{
debug_assert!(
pinned_borrows.is_none_or(|p| p.contains(borrow_index)),
pinned_borrows.contains(borrow_index),
"unexpected expired but non-pinned borrow {borrow_index:?}: {borrow:?}",
);
match kind {
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