Move the place in &pin mut $place when !Unpin to ensure soundness

This commit is contained in:
Frank King 2025-04-04 12:15:23 +08:00
parent 2090f40770
commit afdb54a673
9 changed files with 559 additions and 191 deletions

View file

@ -480,15 +480,39 @@ impl<'tcx> ThirBuildCx<'tcx> {
}
// Make `&pin mut $expr` and `&pin const $expr` into
// `Pin { __pointer: &mut $expr }` and `Pin { __pointer: &$expr }`.
hir::ExprKind::AddrOf(hir::BorrowKind::Pin, mutbl, arg) => match expr_ty.kind() {
&ty::Adt(adt_def, args)
if tcx.is_lang_item(adt_def.did(), rustc_hir::LangItem::Pin) =>
{
let arg = self.mirror_expr(arg);
// `Pin { __pointer: &mut { $expr } }` and `Pin { __pointer: &$expr }`.
hir::ExprKind::AddrOf(hir::BorrowKind::Pin, mutbl, arg_expr) => match expr_ty.kind() {
&ty::Adt(adt_def, args) if tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin) => {
let ty = args.type_at(0);
let arg_ty = self.typeck_results.expr_ty(arg_expr);
let mut arg = self.mirror_expr(arg_expr);
// For `&pin mut $place` where `$place` is not `Unpin`, move the place
// `$place` to ensure it will not be used afterwards.
if mutbl.is_mut() && !arg_ty.is_unpin(self.tcx, self.typing_env) {
let block = self.thir.blocks.push(Block {
targeted_by_break: false,
region_scope: region::Scope {
local_id: arg_expr.hir_id.local_id,
data: region::ScopeData::Node,
},
span: arg_expr.span,
stmts: Box::new([]),
expr: Some(arg),
safety_mode: BlockSafety::Safe,
});
let (temp_lifetime, backwards_incompatible) = self
.rvalue_scopes
.temporary_scope(self.region_scope_tree, arg_expr.hir_id.local_id);
arg = self.thir.exprs.push(Expr {
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
ty: arg_ty,
span: arg_expr.span,
kind: ExprKind::Block { block },
});
}
let expr = self.thir.exprs.push(Expr {
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
ty: args.type_at(0),
ty,
span: expr.span,
kind: ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg },
});

View file

@ -2,7 +2,8 @@
//@ pretty-mode:hir
//@ pp-exact:pin-ergonomics-hir.pp
#![feature(pin_ergonomics)]#![allow(dead_code, incomplete_features)]
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]

View file

@ -30,7 +30,6 @@ fn bar() {
foo_const(x);
let x: Pin<&_> = &pin const Foo;
foo_const(x);
foo_const(x);
}

View file

@ -1,59 +0,0 @@
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
// Makes sure `&pin mut place` and `&pin const place` cannot violate the mut-xor-share rules.
use std::pin::Pin;
struct Foo;
fn foo_mut(_: &mut Foo) {
}
fn foo_ref(_: &Foo) {
}
fn foo_pin_mut(_: Pin<&mut Foo>) {
}
fn foo_pin_ref(_: Pin<&Foo>) {
}
fn bar() {
let foo = Foo;
foo_pin_mut(&pin mut foo); //~ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable
let mut foo = Foo;
let x = &pin mut foo;
foo_pin_ref(&pin const foo); //~ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
foo_pin_mut(&pin mut foo); //~ ERROR cannot borrow `foo` as mutable more than once at a time
foo_ref(&foo); //~ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
foo_mut(&mut foo); //~ ERROR cannot borrow `foo` as mutable more than once at a time
foo_pin_mut(x);
let mut foo = Foo;
let x = &pin const foo;
foo_pin_ref(&pin const foo); // ok
foo_pin_mut(&pin mut foo); //~ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable
foo_ref(&foo); // ok
foo_mut(&mut foo); //~ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable
foo_pin_ref(x);
let mut foo = Foo;
let x = &mut foo;
foo_pin_ref(&pin const foo); //~ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
foo_pin_mut(&pin mut foo); //~ ERROR cannot borrow `foo` as mutable more than once at a time
foo_mut(x);
let mut foo = Foo;
let x = &foo;
foo_pin_ref(&pin const foo); // ok
foo_pin_mut(&pin mut foo); //~ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable
foo_ref(x);
}
fn main() {}

View file

@ -1,121 +0,0 @@
error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
--> $DIR/borrow-mut-xor-share.rs:24:17
|
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ cannot borrow as mutable
|
help: consider changing this to be mutable
|
LL | let mut foo = Foo;
| +++
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrow-mut-xor-share.rs:28:17
|
LL | let x = &pin mut foo;
| ------------ mutable borrow occurs here
LL | foo_pin_ref(&pin const foo);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
...
LL | foo_pin_mut(x);
| - mutable borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/borrow-mut-xor-share.rs:29:17
|
LL | let x = &pin mut foo;
| ------------ first mutable borrow occurs here
LL | foo_pin_ref(&pin const foo);
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ second mutable borrow occurs here
...
LL | foo_pin_mut(x);
| - first borrow later used here
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrow-mut-xor-share.rs:30:13
|
LL | let x = &pin mut foo;
| ------------ mutable borrow occurs here
...
LL | foo_ref(&foo);
| ^^^^ immutable borrow occurs here
...
LL | foo_pin_mut(x);
| - mutable borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/borrow-mut-xor-share.rs:31:13
|
LL | let x = &pin mut foo;
| ------------ first mutable borrow occurs here
...
LL | foo_mut(&mut foo);
| ^^^^^^^^ second mutable borrow occurs here
LL |
LL | foo_pin_mut(x);
| - first borrow later used here
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
--> $DIR/borrow-mut-xor-share.rs:38:17
|
LL | let x = &pin const foo;
| -------------- immutable borrow occurs here
LL | foo_pin_ref(&pin const foo); // ok
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ mutable borrow occurs here
...
LL | foo_pin_ref(x);
| - immutable borrow later used here
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
--> $DIR/borrow-mut-xor-share.rs:40:13
|
LL | let x = &pin const foo;
| -------------- immutable borrow occurs here
...
LL | foo_mut(&mut foo);
| ^^^^^^^^ mutable borrow occurs here
LL |
LL | foo_pin_ref(x);
| - immutable borrow later used here
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrow-mut-xor-share.rs:46:17
|
LL | let x = &mut foo;
| -------- mutable borrow occurs here
LL | foo_pin_ref(&pin const foo);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
...
LL | foo_mut(x);
| - mutable borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/borrow-mut-xor-share.rs:47:17
|
LL | let x = &mut foo;
| -------- first mutable borrow occurs here
LL | foo_pin_ref(&pin const foo);
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ second mutable borrow occurs here
LL |
LL | foo_mut(x);
| - first borrow later used here
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
--> $DIR/borrow-mut-xor-share.rs:54:17
|
LL | let x = &foo;
| ---- immutable borrow occurs here
LL | foo_pin_ref(&pin const foo); // ok
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ mutable borrow occurs here
LL |
LL | foo_ref(x);
| - immutable borrow later used here
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0499, E0502, E0596.
For more information about an error, try `rustc --explain E0499`.

View file

@ -0,0 +1,238 @@
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:39:14
|
LL | let foo = Foo::default();
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo_pin_mut(&pin mut foo);
| --- value moved here
LL | foo_move(foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | foo_pin_mut(&pin mut foo);
| --- you could clone this value
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:43:14
|
LL | let foo = Foo::default();
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | let x = &pin mut foo;
| --- value moved here
LL | foo_move(foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo;
| --- you could clone this value
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:52:14
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo_pin_mut(&pin mut foo); // ok
| --- value moved here
LL | foo_move(foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | foo_pin_mut(&pin mut foo); // ok
| --- you could clone this value
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:56:14
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | let x = &pin mut foo; // ok
| --- value moved here
LL | foo_move(foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo; // ok
| --- you could clone this value
error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:68:14
|
LL | let foo = Foo::default();
| --- binding `foo` declared here
LL | let x = &pin const foo; // ok
| -------------- borrow of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here
LL |
LL | foo_pin_ref(x);
| - borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin const foo; // ok
| --- you could clone this value
error[E0382]: borrow of moved value: `foo`
--> $DIR/borrow-unpin.rs:76:13
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo_pin_mut(&pin mut foo); // ok
| --- value moved here
LL | foo_ref(&foo);
| ^^^^ value borrowed here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | foo_pin_mut(&pin mut foo); // ok
| --- you could clone this value
error[E0382]: borrow of moved value: `foo`
--> $DIR/borrow-unpin.rs:80:13
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | let x = &pin mut foo; // ok
| --- value moved here
LL | foo_ref(&foo);
| ^^^^ value borrowed here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo; // ok
| --- you could clone this value
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:99:26
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo_pin_mut(&pin mut foo); // ok
| --- value moved here
LL | foo_pin_mut(&pin mut foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | foo_pin_mut(&pin mut foo); // ok
| --- you could clone this value
error[E0382]: use of moved value: `foo`
--> $DIR/borrow-unpin.rs:103:26
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | let x = &pin mut foo; // ok
| --- value moved here
LL | foo_pin_mut(&pin mut foo);
| ^^^ value used here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo; // ok
| --- you could clone this value
error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:115:26
|
LL | let mut foo = Foo::default();
| ------- binding `foo` declared here
LL | let x = &pin const foo; // ok
| -------------- borrow of `foo` occurs here
LL | foo_pin_mut(&pin mut foo);
| ^^^ move out of `foo` occurs here
LL |
LL | foo_pin_ref(x);
| - borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin const foo; // ok
| --- you could clone this value
error[E0382]: borrow of moved value: `foo`
--> $DIR/borrow-unpin.rs:123:17
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo_pin_mut(&pin mut foo); // ok
| --- value moved here
LL | foo_pin_ref(&pin const foo);
| ^^^^^^^^^^^^^^ value borrowed here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | foo_pin_mut(&pin mut foo); // ok
| --- you could clone this value
error[E0382]: borrow of moved value: `foo`
--> $DIR/borrow-unpin.rs:127:17
|
LL | let mut foo = Foo::default();
| ------- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | let x = &pin mut foo; // ok
| --- value moved here
LL | foo_pin_ref(&pin const foo);
| ^^^^^^^^^^^^^^ value borrowed here after move
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:16:1
|
LL | struct Foo(PhantomPinned);
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo; // ok
| --- you could clone this value
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0382, E0505.
For more information about an error, try `rustc --explain E0382`.

View file

@ -0,0 +1,143 @@
//@ revisions: unpin pinned
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
// For now, in order to ensure soundness, we move the place in `&pin mut place`
// if `place` is not `Unpin`.
// In the next step, we borrow the place instead of moving it, after that we
// have to makes sure `&pin mut place` and `&pin const place` cannot violate
// the mut-xor-share rules.
use std::pin::Pin;
use std::marker::PhantomPinned;
#[cfg(pinned)]
#[derive(Default)]
struct Foo(PhantomPinned);
#[cfg(unpin)]
#[derive(Default)]
struct Foo;
fn foo_mut(_: &mut Foo) {
}
fn foo_ref(_: &Foo) {
}
fn foo_pin_mut(_: Pin<&mut Foo>) {
}
fn foo_pin_ref(_: Pin<&Foo>) {
}
fn foo_move(_: Foo) {}
fn immutable_pin_mut_then_move() {
let foo = Foo::default();
foo_pin_mut(&pin mut foo); //[unpin]~ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable
foo_move(foo); //[pinned]~ ERROR use of moved value: `foo`
let foo = Foo::default();
let x = &pin mut foo; //[unpin]~ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable
foo_move(foo); //[pinned]~ ERROR use of moved value: `foo`
//[unpin]~^ ERROR cannot move out of `foo` because it is borrowed
foo_pin_mut(x); //
}
fn pin_mut_then_move() {
let mut foo = Foo::default();
foo_pin_mut(&pin mut foo); // ok
foo_move(foo); //[pinned]~ ERROR use of moved value: `foo`
let mut foo = Foo::default();
let x = &pin mut foo; // ok
foo_move(foo); //[pinned]~ ERROR use of moved value: `foo`
//[unpin]~^ ERROR cannot move out of `foo` because it is borrowed
foo_pin_mut(x); //
}
fn pin_ref_then_move() {
let foo = Foo::default();
foo_pin_ref(&pin const foo); // ok
foo_move(foo); // ok
let foo = Foo::default();
let x = &pin const foo; // ok
foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is borrowed
//[unpin]~^ ERROR cannot move out of `foo` because it is borrowed
foo_pin_ref(x);
}
fn pin_mut_then_ref() {
let mut foo = Foo::default();
foo_pin_mut(&pin mut foo); // ok
foo_ref(&foo); //[pinned]~ ERROR borrow of moved value: `foo`
let mut foo = Foo::default();
let x = &pin mut foo; // ok
foo_ref(&foo); //[pinned]~ ERROR borrow of moved value: `foo`
//[unpin]~^ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
foo_pin_mut(x);
}
fn pin_ref_then_ref() {
let mut foo = Foo::default();
foo_pin_ref(&pin const foo); // ok
foo_ref(&foo); // ok
let mut foo = Foo::default();
let x = &pin const foo; // ok
foo_ref(&foo); // ok
foo_pin_ref(x);
}
fn pin_mut_then_pin_mut() {
let mut foo = Foo::default();
foo_pin_mut(&pin mut foo); // ok
foo_pin_mut(&pin mut foo); //[pinned]~ ERROR use of moved value: `foo`
let mut foo = Foo::default();
let x = &pin mut foo; // ok
foo_pin_mut(&pin mut foo); //[pinned]~ ERROR use of moved value: `foo`
//[unpin]~^ ERROR cannot borrow `foo` as mutable more than once at a time
foo_pin_mut(x);
}
fn pin_ref_then_pin_mut() {
let mut foo = Foo::default();
foo_pin_ref(&pin const foo); // ok
foo_pin_mut(&pin mut foo); // ok
let mut foo = Foo::default();
let x = &pin const foo; // ok
foo_pin_mut(&pin mut foo); //[pinned]~ ERROR cannot move out of `foo` because it is borrowed
//[unpin]~^ ERROR cannot borrow `foo` as mutable because it is also borrowed as immutable
foo_pin_ref(x);
}
fn pin_mut_then_pin_ref() {
let mut foo = Foo::default();
foo_pin_mut(&pin mut foo); // ok
foo_pin_ref(&pin const foo); //[pinned]~ ERROR borrow of moved value: `foo`
let mut foo = Foo::default();
let x = &pin mut foo; // ok
foo_pin_ref(&pin const foo); //[pinned]~ ERROR borrow of moved value: `foo`
//[unpin]~^ ERROR cannot borrow `foo` as immutable because it is also borrowed as mutable
foo_pin_mut(x);
}
fn pin_ref_then_pin_ref() {
let mut foo = Foo::default();
foo_pin_ref(&pin const foo); // ok
foo_pin_ref(&pin const foo); // ok
let mut foo = Foo::default();
let x = &pin const foo; // ok
foo_pin_ref(&pin const foo); // ok
foo_pin_ref(x);
}
fn main() {}

View file

@ -0,0 +1,136 @@
error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
--> $DIR/borrow-unpin.rs:38:17
|
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ cannot borrow as mutable
|
help: consider changing this to be mutable
|
LL | let mut foo = Foo::default();
| +++
error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
--> $DIR/borrow-unpin.rs:42:13
|
LL | let x = &pin mut foo;
| ^^^^^^^^^^^^ cannot borrow as mutable
|
help: consider changing this to be mutable
|
LL | let mut foo = Foo::default();
| +++
error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:43:14
|
LL | let foo = Foo::default();
| --- binding `foo` declared here
LL | let x = &pin mut foo;
| ------------ borrow of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here
LL |
LL | foo_pin_mut(x); //
| - borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:20:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo;
| --- you could clone this value
error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:56:14
|
LL | let mut foo = Foo::default();
| ------- binding `foo` declared here
LL | let x = &pin mut foo; // ok
| ------------ borrow of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here
LL |
LL | foo_pin_mut(x); //
| - borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:20:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin mut foo; // ok
| --- you could clone this value
error[E0505]: cannot move out of `foo` because it is borrowed
--> $DIR/borrow-unpin.rs:68:14
|
LL | let foo = Foo::default();
| --- binding `foo` declared here
LL | let x = &pin const foo; // ok
| -------------- borrow of `foo` occurs here
LL | foo_move(foo);
| ^^^ move out of `foo` occurs here
LL |
LL | foo_pin_ref(x);
| - borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/borrow-unpin.rs:20:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = &pin const foo; // ok
| --- you could clone this value
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrow-unpin.rs:80:13
|
LL | let x = &pin mut foo; // ok
| ------------ mutable borrow occurs here
LL | foo_ref(&foo);
| ^^^^ immutable borrow occurs here
LL |
LL | foo_pin_mut(x);
| - mutable borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/borrow-unpin.rs:103:17
|
LL | let x = &pin mut foo; // ok
| ------------ first mutable borrow occurs here
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ second mutable borrow occurs here
LL |
LL | foo_pin_mut(x);
| - first borrow later used here
error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
--> $DIR/borrow-unpin.rs:115:17
|
LL | let x = &pin const foo; // ok
| -------------- immutable borrow occurs here
LL | foo_pin_mut(&pin mut foo);
| ^^^^^^^^^^^^ mutable borrow occurs here
LL |
LL | foo_pin_ref(x);
| - immutable borrow later used here
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrow-unpin.rs:127:17
|
LL | let x = &pin mut foo; // ok
| ------------ mutable borrow occurs here
LL | foo_pin_ref(&pin const foo);
| ^^^^^^^^^^^^^^ immutable borrow occurs here
LL |
LL | foo_pin_mut(x);
| - mutable borrow later used here
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0499, E0502, E0505, E0596.
For more information about an error, try `rustc --explain E0499`.

View file

@ -1,10 +1,9 @@
//@ check-pass
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
// Makes sure we can handle `&pin mut place` and `&pin const place` as sugar for
// `unsafe { Pin::new_unchecked(&mut place) }` and `Pin::new(&place)`.
// `std::pin::pin!(place)` and `Pin::new(&place)`.
use std::pin::Pin;
@ -28,4 +27,12 @@ fn bar() {
foo_pin_ref(x);
}
fn baz(mut x: Foo, y: Foo) {
let _x = &pin mut x;
let _x = x; // ok because `Foo: Unpin` and thus `&pin mut x` doesn't move `x`
let _y = &pin const y;
let _y = y; // ok because `&pin const y` dosn't move `y`
}
fn main() {}