diff options
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 38 | ||||
| -rw-r--r-- | tests/pretty/pin-ergonomics-hir.pp | 3 | ||||
| -rw-r--r-- | tests/pretty/pin-ergonomics.rs | 1 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow-mut-xor-share.rs | 59 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow-mut-xor-share.stderr | 121 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr | 238 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow-unpin.rs | 143 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr | 136 | ||||
| -rw-r--r-- | tests/ui/pin-ergonomics/borrow.rs | 11 |
9 files changed, 559 insertions, 191 deletions
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 52de0395ab6..764b7efe2a3 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -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 }, }); diff --git a/tests/pretty/pin-ergonomics-hir.pp b/tests/pretty/pin-ergonomics-hir.pp index 42405982f92..212e0e174da 100644 --- a/tests/pretty/pin-ergonomics-hir.pp +++ b/tests/pretty/pin-ergonomics-hir.pp @@ -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] diff --git a/tests/pretty/pin-ergonomics.rs b/tests/pretty/pin-ergonomics.rs index 54a57545c55..8e8ced791b1 100644 --- a/tests/pretty/pin-ergonomics.rs +++ b/tests/pretty/pin-ergonomics.rs @@ -30,7 +30,6 @@ fn bar() { foo_const(x); let x: Pin<&_> = &pin const Foo; - foo_const(x); foo_const(x); } diff --git a/tests/ui/pin-ergonomics/borrow-mut-xor-share.rs b/tests/ui/pin-ergonomics/borrow-mut-xor-share.rs deleted file mode 100644 index c5363eafef5..00000000000 --- a/tests/ui/pin-ergonomics/borrow-mut-xor-share.rs +++ /dev/null @@ -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() {} diff --git a/tests/ui/pin-ergonomics/borrow-mut-xor-share.stderr b/tests/ui/pin-ergonomics/borrow-mut-xor-share.stderr deleted file mode 100644 index 47d990b2ec9..00000000000 --- a/tests/ui/pin-ergonomics/borrow-mut-xor-share.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr new file mode 100644 index 00000000000..cc438461a5d --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -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`. diff --git a/tests/ui/pin-ergonomics/borrow-unpin.rs b/tests/ui/pin-ergonomics/borrow-unpin.rs new file mode 100644 index 00000000000..61e69bab12b --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.rs @@ -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() {} diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr new file mode 100644 index 00000000000..bf9921343ee --- /dev/null +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -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`. diff --git a/tests/ui/pin-ergonomics/borrow.rs b/tests/ui/pin-ergonomics/borrow.rs index e33f3c1fa26..f221165848b 100644 --- a/tests/ui/pin-ergonomics/borrow.rs +++ b/tests/ui/pin-ergonomics/borrow.rs @@ -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() {} |
