Move the place in &pin mut $place when !Unpin to ensure soundness
This commit is contained in:
parent
2090f40770
commit
afdb54a673
9 changed files with 559 additions and 191 deletions
|
|
@ -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 },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ fn bar() {
|
|||
foo_const(x);
|
||||
|
||||
let x: Pin<&_> = &pin const Foo;
|
||||
|
||||
foo_const(x);
|
||||
foo_const(x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
238
tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr
Normal file
238
tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr
Normal 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`.
|
||||
143
tests/ui/pin-ergonomics/borrow-unpin.rs
Normal file
143
tests/ui/pin-ergonomics/borrow-unpin.rs
Normal 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() {}
|
||||
136
tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr
Normal file
136
tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr
Normal 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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue