Implement pinned borrows, part of pin_ergonomics

This commit is contained in:
Frank King
2025-01-19 22:01:11 +08:00
parent 49a8ba0684
commit e627f88f88
18 changed files with 471 additions and 18 deletions

View File

@@ -898,6 +898,10 @@ pub enum BorrowKind {
/// The resulting type is either `*const T` or `*mut T`
/// where `T = typeof($expr)`.
Raw,
/// A pinned borrow, `&pin const $expr` or `&pin mut $expr`.
/// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>`
/// where `T = typeof($expr)` and `'a` is some lifetime.
Pin,
}
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]

View File

@@ -357,6 +357,10 @@ impl<'a> State<'a> {
self.word_nbsp("raw");
self.print_mutability(mutability, true);
}
ast::BorrowKind::Pin => {
self.word_nbsp("pin");
self.print_mutability(mutability, true);
}
}
self.print_expr_cond_paren(
expr,

View File

@@ -616,11 +616,13 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
}),
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
}),
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
ccx.dcx().create_err(errors::MutableRefEscaping {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
})
}
}
}
}

View File

@@ -1339,6 +1339,10 @@ impl<'a> State<'a> {
self.word_nbsp("raw");
self.print_mutability(mutability, true);
}
hir::BorrowKind::Pin => {
self.word_nbsp("pin");
self.print_mutability(mutability, true);
}
}
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
}

View File

@@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_named_place_expr(oprnd);
Ty::new_ptr(self.tcx, ty, mutbl)
}
hir::BorrowKind::Ref => {
hir::BorrowKind::Ref | hir::BorrowKind::Pin => {
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
@@ -680,7 +680,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// whose address was taken can actually be made to live as long
// as it needs to live.
let region = self.next_region_var(infer::BorrowRegion(expr.span));
Ty::new_ref(self.tcx, region, ty, mutbl)
match kind {
hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl),
hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl),
_ => unreachable!(),
}
}
}
}

View File

@@ -479,6 +479,31 @@ impl<'tcx> ThirBuildCx<'tcx> {
ExprKind::RawBorrow { mutability, arg: self.mirror_expr(arg) }
}
// 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);
let expr = self.thir.exprs.push(Expr {
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
ty: args.type_at(0),
span: expr.span,
kind: ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg },
});
ExprKind::Adt(Box::new(AdtExpr {
adt_def,
variant_index: FIRST_VARIANT,
args,
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
user_ty: None,
base: AdtExprBase::None,
}))
}
_ => span_bug!(expr.span, "unexpected type for pinned borrow: {:?}", expr_ty),
},
hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
hir::ExprKind::Assign(lhs, rhs, _) => {

View File

@@ -847,7 +847,7 @@ impl<'a> Parser<'a> {
self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
}
/// Parse `mut?` or `raw [ const | mut ]`.
/// Parse `mut?` or `[ raw | pin ] [ const | mut ]`.
fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) {
// `raw [ const | mut ]`.
@@ -855,6 +855,11 @@ impl<'a> Parser<'a> {
assert!(found_raw);
let mutability = self.parse_const_or_mut().unwrap();
(ast::BorrowKind::Raw, mutability)
} else if let Some((ast::Pinnedness::Pinned, mutbl)) = self.parse_pin_and_mut() {
// `pin [ const | mut ]`.
// `pin` has been gated in `self.parse_pin_and_mut()` so we don't
// need to gate it here.
(ast::BorrowKind::Pin, mutbl)
} else {
// `mut?`
(ast::BorrowKind::Ref, self.parse_mutability())

View File

@@ -2289,8 +2289,10 @@ fn rewrite_expr_addrof(
) -> RewriteResult {
let operator_str = match (mutability, borrow_kind) {
(ast::Mutability::Not, ast::BorrowKind::Ref) => "&",
(ast::Mutability::Not, ast::BorrowKind::Pin) => "&pin const ",
(ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ",
(ast::Mutability::Mut, ast::BorrowKind::Ref) => "&mut ",
(ast::Mutability::Mut, ast::BorrowKind::Pin) => "&pin mut ",
(ast::Mutability::Mut, ast::BorrowKind::Raw) => "&raw mut ",
};
rewrite_unary_prefix(context, operator_str, expr, shape)

View File

@@ -18,3 +18,13 @@ impl Foo {
mut self) {}
fn i(&pin mut self) {}
}
fn borrows() {
let mut foo = 0_i32;
let x: Pin<&mut _> = & pin
mut foo;
let x: Pin<&_> = &
pin const
foo;
}

View File

@@ -16,3 +16,10 @@ impl Foo {
fn h<'a>(&'a pin mut self) {}
fn i(&pin mut self) {}
}
fn borrows() {
let mut foo = 0_i32;
let x: Pin<&mut _> = &pin mut foo;
let x: Pin<&_> = &pin const foo;
}

View File

@@ -0,0 +1,43 @@
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:pin-ergonomics-hir.pp
#![feature(pin_ergonomics)]#![allow(dead_code, incomplete_features)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
use std::pin::Pin;
struct Foo;
impl Foo {
fn baz(&mut self) { }
fn baz_const(&self) { }
fn baz_lt<'a>(&mut self) { }
fn baz_const_lt(&self) { }
}
fn foo(_: Pin<&'_ mut Foo>) { }
fn foo_lt<'a>(_: Pin<&'a mut Foo>) { }
fn foo_const(_: Pin<&'_ Foo>) { }
fn foo_const_lt(_: Pin<&'_ Foo>) { }
fn bar() {
let mut x: Pin<&mut _> = &pin mut Foo;
foo(x.as_mut());
foo(x.as_mut());
foo_const(x);
let x: Pin<&_> = &pin const Foo;
foo_const(x);
foo_const(x);
}
fn main() { }

View File

@@ -0,0 +1,40 @@
//@ pretty-compare-only
//@ pretty-mode:hir
//@ pp-exact:pin-ergonomics-hir.pp
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
use std::pin::Pin;
struct Foo;
impl Foo {
fn baz(&mut self) { }
fn baz_const(&self) { }
fn baz_lt<'a>(&mut self) { }
fn baz_const_lt(&self) { }
}
fn foo(_: Pin<&'_ mut Foo>) { }
fn foo_lt<'a>(_: Pin<&'a mut Foo>) { }
fn foo_const(_: Pin<&'_ Foo>) { }
fn foo_const_lt(_: Pin<&'_ Foo>) { }
fn bar() {
let mut x: Pin<&mut _> = &pin mut Foo;
foo(x.as_mut());
foo(x.as_mut());
foo_const(x);
let x: Pin<&_> = &pin const Foo;
foo_const(x);
foo_const(x);
}
fn main() { }

View File

@@ -3,6 +3,8 @@
#![feature(pin_ergonomics)]
#![allow(dead_code, incomplete_features)]
use std::pin::Pin;
struct Foo;
impl Foo {
@@ -21,4 +23,16 @@ fn foo_lt<'a>(_: &'a pin mut Foo) {}
fn foo_const(_: &pin const Foo) {}
fn foo_const_lt(_: &'_ pin const Foo) {}
fn bar() {
let mut x: Pin<&mut _> = &pin mut Foo;
foo(x.as_mut());
foo(x.as_mut());
foo_const(x);
let x: Pin<&_> = &pin const Foo;
foo_const(x);
foo_const(x);
}
fn main() {}

View File

@@ -0,0 +1,59 @@
#![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

@@ -0,0 +1,121 @@
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,31 @@
//@ 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)`.
use std::pin::Pin;
struct Foo;
fn foo_pin_mut(_: Pin<&mut Foo>) {
}
fn foo_pin_ref(_: Pin<&Foo>) {
}
fn bar() {
let mut x: Pin<&mut _> = &pin mut Foo;
foo_pin_mut(x.as_mut());
foo_pin_mut(x.as_mut());
foo_pin_ref(x);
let x: Pin<&_> = &pin const Foo;
foo_pin_ref(x);
foo_pin_ref(x);
}
fn main() {}

View File

@@ -17,6 +17,10 @@ fn foo(mut x: Pin<&mut Foo>) {
let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental
}
fn foo_const(x: Pin<&Foo>) {
let _y: &pin const Foo = x; //~ ERROR pinned reference syntax is experimental
}
fn foo_sugar(_: &pin mut Foo) {} //~ ERROR pinned reference syntax is experimental
fn bar(x: Pin<&mut Foo>) {
@@ -31,6 +35,18 @@ fn baz(mut x: Pin<&mut Foo>) {
fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental
fn borrows() {
let mut x: Pin<&mut _> = &pin mut Foo; //~ ERROR pinned reference syntax is experimental
foo(x.as_mut());
foo(x.as_mut());
foo_const(x.as_ref());
let x: Pin<&_> = &pin const Foo; //~ ERROR pinned reference syntax is experimental
foo_const(x);
foo_const(x);
}
#[cfg(any())]
mod not_compiled {
use std::pin::Pin;
@@ -63,6 +79,18 @@ mod not_compiled {
}
fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental
fn borrows() {
let mut x: Pin<&mut _> = &pin mut Foo; //~ ERROR pinned reference syntax is experimental
foo(x.as_mut());
foo(x.as_mut());
foo_const(x.as_ref());
let x: Pin<&_> = &pin const Foo; //~ ERROR pinned reference syntax is experimental
foo_const(x);
foo_const(x);
}
}
fn main() {}

View File

@@ -29,7 +29,17 @@ LL | let _y: &pin mut Foo = x;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:20:18
--> $DIR/feature-gate-pin_ergonomics.rs:21:14
|
LL | let _y: &pin const Foo = x;
| ^^^
|
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:24:18
|
LL | fn foo_sugar(_: &pin mut Foo) {}
| ^^^
@@ -39,7 +49,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:32:18
--> $DIR/feature-gate-pin_ergonomics.rs:36:18
|
LL | fn baz_sugar(_: &pin const Foo) {}
| ^^^
@@ -49,7 +59,27 @@ LL | fn baz_sugar(_: &pin const Foo) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:43:23
--> $DIR/feature-gate-pin_ergonomics.rs:39:31
|
LL | let mut x: Pin<&mut _> = &pin mut Foo;
| ^^^
|
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:44:23
|
LL | let x: Pin<&_> = &pin const Foo;
| ^^^
|
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:59:23
|
LL | fn foo_sugar(&pin mut self) {}
| ^^^
@@ -59,7 +89,7 @@ LL | fn foo_sugar(&pin mut self) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:44:29
--> $DIR/feature-gate-pin_ergonomics.rs:60:29
|
LL | fn foo_sugar_const(&pin const self) {}
| ^^^
@@ -69,7 +99,7 @@ LL | fn foo_sugar_const(&pin const self) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:50:18
--> $DIR/feature-gate-pin_ergonomics.rs:66:18
|
LL | let _y: &pin mut Foo = x;
| ^^^
@@ -79,7 +109,7 @@ LL | let _y: &pin mut Foo = x;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:53:22
--> $DIR/feature-gate-pin_ergonomics.rs:69:22
|
LL | fn foo_sugar(_: &pin mut Foo) {}
| ^^^
@@ -89,7 +119,7 @@ LL | fn foo_sugar(_: &pin mut Foo) {}
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:65:22
--> $DIR/feature-gate-pin_ergonomics.rs:81:22
|
LL | fn baz_sugar(_: &pin const Foo) {}
| ^^^
@@ -98,8 +128,28 @@ LL | fn baz_sugar(_: &pin const Foo) {}
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:84:35
|
LL | let mut x: Pin<&mut _> = &pin mut Foo;
| ^^^
|
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: pinned reference syntax is experimental
--> $DIR/feature-gate-pin_ergonomics.rs:89:27
|
LL | let x: Pin<&_> = &pin const Foo;
| ^^^
|
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0382]: use of moved value: `x`
--> $DIR/feature-gate-pin_ergonomics.rs:24:9
--> $DIR/feature-gate-pin_ergonomics.rs:28:9
|
LL | fn bar(x: Pin<&mut Foo>) {
| - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
@@ -117,7 +167,7 @@ LL | fn foo(mut x: Pin<&mut Foo>) {
| in this function
error[E0382]: use of moved value: `x`
--> $DIR/feature-gate-pin_ergonomics.rs:29:5
--> $DIR/feature-gate-pin_ergonomics.rs:33:5
|
LL | fn baz(mut x: Pin<&mut Foo>) {
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
@@ -136,7 +186,7 @@ help: consider reborrowing the `Pin` instead of moving it
LL | x.as_mut().foo();
| +++++++++
error: aborting due to 12 previous errors
error: aborting due to 17 previous errors
Some errors have detailed explanations: E0382, E0658.
For more information about an error, try `rustc --explain E0382`.