Skip to content

Commit c79db9c

Browse files
committed
Suggest Pin::as_mut when encountering borrow error
1 parent 984eab5 commit c79db9c

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11331133
place_name, partially_str, loop_message
11341134
),
11351135
);
1136+
if let ty::Adt(def, ..)
1137+
= moved_place.ty(self.body, self.infcx.tcx).ty.kind()
1138+
&& Some(def.did()) == self.infcx.tcx.lang_items().pin_type()
1139+
{
1140+
err.span_suggestion_verbose(
1141+
fn_call_span.shrink_to_lo(),
1142+
"consider reborrowing the `Pin` instead of moving it",
1143+
"as_mut().".to_string(),
1144+
Applicability::MaybeIncorrect,
1145+
);
1146+
}
11361147
}
11371148
let tcx = self.infcx.tcx;
11381149
// Avoid pointing to the same function in multiple different

src/test/ui/moves/move-fn-self-receiver.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which move
6767
|
6868
LL | fn use_pin_box_self(self: Pin<Box<Self>>) {}
6969
| ^^^^
70+
help: consider reborrowing the `Pin` instead of moving it
71+
|
72+
LL | pin_box_foo.as_mut().use_pin_box_self();
73+
| +++++++++
7074

7175
error[E0505]: cannot move out of `mut_foo` because it is borrowed
7276
--> $DIR/move-fn-self-receiver.rs:50:5
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
use std::pin::Pin;
3+
4+
struct Foo;
5+
6+
impl Foo {
7+
fn foo(self: Pin<&mut Self>) {}
8+
}
9+
10+
fn main() {
11+
let mut foo = Foo;
12+
let mut foo = Pin::new(&mut foo);
13+
foo.as_mut().foo();
14+
foo.foo(); //~ ERROR use of moved value
15+
}

src/test/ui/moves/pin-mut-reborrow.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
use std::pin::Pin;
3+
4+
struct Foo;
5+
6+
impl Foo {
7+
fn foo(self: Pin<&mut Self>) {}
8+
}
9+
10+
fn main() {
11+
let mut foo = Foo;
12+
let mut foo = Pin::new(&mut foo);
13+
foo.foo();
14+
foo.foo(); //~ ERROR use of moved value
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0382]: use of moved value: `foo`
2+
--> $DIR/pin-mut-reborrow.rs:14:5
3+
|
4+
LL | let mut foo = Pin::new(&mut foo);
5+
| ------- move occurs because `foo` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
6+
LL | foo.foo();
7+
| ----- `foo` moved due to this method call
8+
LL | foo.foo();
9+
| ^^^ value used here after move
10+
|
11+
note: `Foo::foo` takes ownership of the receiver `self`, which moves `foo`
12+
--> $DIR/pin-mut-reborrow.rs:7:12
13+
|
14+
LL | fn foo(self: Pin<&mut Self>) {}
15+
| ^^^^
16+
help: consider reborrowing the `Pin` instead of moving it
17+
|
18+
LL | foo.as_mut().foo();
19+
| +++++++++
20+
21+
error: aborting due to previous error
22+
23+
For more information about this error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)