Peel off explicit (or implicit) deref before suggesting clone on move error in borrowck

This commit is contained in:
Michael Goulet 2024-07-26 14:32:19 -04:00
parent e7eae5370e
commit 91acacf85b
45 changed files with 111 additions and 351 deletions

View File

@ -570,11 +570,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
} = move_spans
&& can_suggest_clone
{
self.suggest_cloning(err, ty, expr, None, Some(move_spans));
self.suggest_cloning(err, ty, expr, Some(move_spans));
} else if self.suggest_hoisting_call_outside_loop(err, expr) && can_suggest_clone {
// The place where the type moves would be misleading to suggest clone.
// #121466
self.suggest_cloning(err, ty, expr, None, Some(move_spans));
self.suggest_cloning(err, ty, expr, Some(move_spans));
}
}
@ -1236,8 +1236,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
&self,
err: &mut Diag<'_>,
ty: Ty<'tcx>,
mut expr: &'tcx hir::Expr<'tcx>,
mut other_expr: Option<&'tcx hir::Expr<'tcx>>,
expr: &'tcx hir::Expr<'tcx>,
use_spans: Option<UseSpans<'tcx>>,
) {
if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
@ -1249,66 +1248,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
return;
}
if let Some(some_other_expr) = other_expr
&& let Some(parent_binop) =
self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
if let (hir_id, hir::Node::Expr(e)) = n
&& let hir::ExprKind::AssignOp(_binop, target, _arg) = e.kind
&& target.hir_id == expr.hir_id
{
Some(hir_id)
} else {
None
}
})
&& let Some(other_parent_binop) =
self.infcx.tcx.hir().parent_iter(some_other_expr.hir_id).find_map(|n| {
if let (hir_id, hir::Node::Expr(expr)) = n
&& let hir::ExprKind::AssignOp(..) = expr.kind
{
Some(hir_id)
} else {
None
}
})
&& parent_binop == other_parent_binop
{
// Explicitly look for `expr += other_expr;` and avoid suggesting
// `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
other_expr = Some(expr);
expr = some_other_expr;
}
'outer: {
if let ty::Ref(..) = ty.kind() {
// We check for either `let binding = foo(expr, other_expr);` or
// `foo(expr, other_expr);` and if so we don't suggest an incorrect
// `foo(expr, other_expr).clone()`
if let Some(other_expr) = other_expr
&& let Some(parent_let) =
self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
Some(hir_id)
} else {
None
}
})
&& let Some(other_parent_let) =
self.infcx.tcx.hir().parent_iter(other_expr.hir_id).find_map(|n| {
if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
Some(hir_id)
} else {
None
}
})
&& parent_let == other_parent_let
{
// Explicitly check that we don't have `foo(&*expr, other_expr)`, as cloning the
// result of `foo(...)` won't help.
break 'outer;
}
}
}
let ty = ty.peel_refs();
if self.implements_clone(ty) {
self.suggest_cloning_inner(err, ty, expr);
} else if let ty::Adt(def, args) = ty.kind()
@ -1575,10 +1514,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
);
self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
if let Some(expr) = self.find_expr(borrow_span)
&& let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
{
self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
if let Some(expr) = self.find_expr(borrow_span) {
// This is a borrow span, so we want to suggest cloning the referent.
if let hir::ExprKind::AddrOf(_, _, borrowed_expr) = expr.kind
&& let Some(ty) = typeck_results.expr_ty_opt(borrowed_expr)
{
self.suggest_cloning(&mut err, ty, borrowed_expr, Some(move_spans));
} else if typeck_results.expr_adjustments(expr).first().is_some_and(|adj| {
matches!(
adj.kind,
ty::adjustment::Adjust::Borrow(ty::adjustment::AutoBorrow::Ref(
_,
ty::adjustment::AutoBorrowMutability::Not
| ty::adjustment::AutoBorrowMutability::Mut {
allow_two_phase_borrow: ty::adjustment::AllowTwoPhase::No
}
))
)
}) && let Some(ty) = typeck_results.expr_ty_opt(expr)
{
self.suggest_cloning(&mut err, ty, expr, Some(move_spans));
}
}
self.buffer_error(err);
}

View File

@ -565,9 +565,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
match error {
GroupedMoveError::MovesFromPlace {
mut binds_to, move_from, span: other_span, ..
} => {
GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
self.add_borrow_suggestions(err, span);
if binds_to.is_empty() {
let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
@ -577,7 +575,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
};
if let Some(expr) = self.find_expr(span) {
self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None);
self.suggest_cloning(err, place_ty, expr, None);
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@ -609,13 +607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
};
if let Some(expr) = self.find_expr(use_span) {
self.suggest_cloning(
err,
place_ty,
expr,
self.find_expr(span),
Some(use_spans),
);
self.suggest_cloning(err, place_ty, expr, Some(use_spans));
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@ -740,7 +732,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
if let Some(expr) = self.find_expr(binding_span) {
self.suggest_cloning(err, bind_to.ty, expr, None, None);
self.suggest_cloning(err, bind_to.ty, expr, None);
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {

View File

@ -18,7 +18,7 @@ LL | pub fn free_and_use<T: for<'a> Foo<'a>,
| ^ consider constraining this type parameter with `Clone`
...
LL | 's: loop { y = denormalise(&x); break }
| -- you could clone this value
| - you could clone this value
error: aborting due to 1 previous error

View File

@ -17,7 +17,6 @@ fn main() {
x;
//~^ ERROR cannot move out of `x` because it is borrowed
//~| move out of `x` occurs here
//~| HELP consider cloning
let y = Int(2);
//~^ HELP consider changing this to be mutable

View File

@ -8,14 +8,9 @@ LL | x
...
LL | x;
| ^ move out of `x` occurs here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | x.clone();
| ++++++++
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
--> $DIR/augmented-assignments.rs:25:5
--> $DIR/augmented-assignments.rs:24:5
|
LL | y
| ^ cannot borrow as mutable

View File

@ -65,7 +65,7 @@ help: if `T` implemented `Clone`, you could clone the value
LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/binop-move-semantics.rs:23:5
@ -88,7 +88,7 @@ LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
LL | let n = &mut y;
| ------ you could clone this value
| - you could clone this value
error[E0507]: cannot move out of `*m` which is behind a mutable reference
--> $DIR/binop-move-semantics.rs:30:5

View File

@ -13,9 +13,8 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let r = &x.0;
LL + let r = x.0.clone();
|
LL | let r = &x.0.clone();
| ++++++++
error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
--> $DIR/borrow-tuple-fields.rs:18:13
@ -51,9 +50,8 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let r = &x.0;
LL + let r = x.0.clone();
|
LL | let r = &x.0.clone();
| ++++++++
error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
--> $DIR/borrow-tuple-fields.rs:33:13

View File

@ -14,7 +14,7 @@ LL | a);
help: consider cloning the value if the performance cost is acceptable
|
LL - &*a,
LL + a.clone(),
LL + &a.clone(),
|
error[E0505]: cannot move out of `a` because it is borrowed
@ -32,7 +32,7 @@ LL | a);
help: consider cloning the value if the performance cost is acceptable
|
LL - &*a,
LL + a.clone(),
LL + &a.clone(),
|
error: aborting due to 2 previous errors

View File

@ -52,9 +52,8 @@ LL | drop(**p);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let p = &x.b;
LL + let p = x.b.clone();
|
LL | let p = &x.b.clone();
| ++++++++
error[E0505]: cannot move out of `x.b` because it is borrowed
--> $DIR/borrowck-field-sensitivity.rs:41:14
@ -70,9 +69,8 @@ LL | drop(**p);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let p = &x.b;
LL + let p = x.b.clone();
|
LL | let p = &x.b.clone();
| ++++++++
error[E0499]: cannot borrow `x.a` as mutable more than once at a time
--> $DIR/borrowck-field-sensitivity.rs:48:13

View File

@ -17,11 +17,6 @@ LL | {src};
| --- value moved here
LL | src.0 = 66;
| ^^^^^^^^^^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | {src.clone()};
| ++++++++
error: aborting due to 2 previous errors

View File

@ -16,9 +16,8 @@ LL | w.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let w = &v;
LL + let w = v.clone();
|
LL | let w = &v.clone();
| ++++++++
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/borrowck-loan-blocks-move-cc.rs:24:19
@ -38,9 +37,8 @@ LL | w.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let w = &v;
LL + let w = v.clone();
|
LL | let w = &v.clone();
| ++++++++
error: aborting due to 2 previous errors

View File

@ -12,9 +12,8 @@ LL | w.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let w = &v;
LL + let w = v.clone();
|
LL | let w = &v.clone();
| ++++++++
error: aborting due to 1 previous error

View File

@ -13,9 +13,8 @@ LL | b.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let b = &a;
LL + let b = a.clone();
|
LL | let b = &a.clone();
| ++++++++
error: aborting due to 1 previous error

View File

@ -14,7 +14,7 @@ LL | p.use_ref();
help: consider cloning the value if the performance cost is acceptable
|
LL - let p: &isize = &*t0; // Freezes `*t0`
LL + let p: &isize = t0.clone(); // Freezes `*t0`
LL + let p: &isize = &t0.clone(); // Freezes `*t0`
|
error: aborting due to 1 previous error

View File

@ -17,7 +17,7 @@ LL | struct S {
| ^^^^^^^^ consider implementing `Clone` for this type
...
LL | let pb = &a;
| -- you could clone this value
| - you could clone this value
error: aborting due to 1 previous error

View File

@ -17,9 +17,8 @@ LL | borrow(&*p1);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let p1 = &x1;
LL + let p1 = x1.clone();
|
LL | let p1 = &x1.clone();
| ++++++++
error[E0505]: cannot move out of `x2` because it is borrowed
--> $DIR/borrowck-multiple-captures.rs:12:19
@ -39,9 +38,8 @@ LL | borrow(&*p2);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let p2 = &x2;
LL + let p2 = x2.clone();
|
LL | let p2 = &x2.clone();
| ++++++++
error[E0382]: use of moved value: `x1`
--> $DIR/borrowck-multiple-captures.rs:27:19
@ -108,9 +106,8 @@ LL | borrow(&*p);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let p = &x;
LL + let p = x.clone();
|
LL | let p = &x.clone();
| ++++++++
error[E0382]: use of moved value: `x`
--> $DIR/borrowck-multiple-captures.rs:52:14

View File

@ -11,6 +11,11 @@ LL | println!("{}", f[s]);
...
LL | use_mut(rs);
| -- borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let rs = &mut s.clone();
| ++++++++
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7
@ -25,6 +30,11 @@ LL | f[s] = 10;
...
LL | use_mut(rs);
| -- borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let rs = &mut s.clone();
| ++++++++
error[E0382]: use of moved value: `s`
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7

View File

@ -13,7 +13,7 @@ LL | *y
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = &*x;
LL + let y = x.clone();
LL + let y = &x.clone();
|
error: aborting due to 1 previous error

View File

@ -38,7 +38,7 @@ help: if `T` implemented `Clone`, you could clone the value
LL | fn bar<T: std::fmt::Display>(x: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let a = &x;
| -- you could clone this value
| - you could clone this value
help: consider further restricting this bound
|
LL | fn bar<T: std::fmt::Display + Clone>(x: T) {
@ -66,7 +66,7 @@ LL | struct A;
| ^^^^^^^^ consider implementing `Clone` for this type
LL | fn qux(x: A) {
LL | let a = &x;
| -- you could clone this value
| - you could clone this value
help: consider annotating `A` with `#[derive(Clone)]`
|
LL + #[derive(Clone)]

View File

@ -18,14 +18,6 @@ LL | fn fill_segment(_: &mut State) {}
| ------------ ^^^^^^^^^^ this parameter takes ownership of the value
| |
| in this function
note: if `State` implemented `Clone`, you could clone the value
--> $DIR/issue-101119.rs:1:1
|
LL | struct State;
| ^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | fill_segment(state);
| ----- you could clone this value
error: aborting due to 1 previous error

View File

@ -12,9 +12,8 @@ LL | }
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
LL + let _map = BTreeMap::from_iter([((), PrintOnDrop(s.clone()))]);
|
LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s.clone()))]);
| ++++++++
error: aborting due to 1 previous error

View File

@ -9,11 +9,6 @@ LL | drop(a);
| ^ move out of `a` occurs here
LL | for s in &b {
| -- borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let b: Vec<&str> = a.clone().lines().collect();
| ++++++++
error: aborting due to 1 previous error

View File

@ -21,7 +21,7 @@ LL | struct FancyNum {
| ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let fancy_ref = &fancy_num;
| ---------- you could clone this value
| --------- you could clone this value
error: aborting due to 1 previous error

View File

@ -18,7 +18,7 @@ LL | struct Value {}
| ^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let _ref_to_val: &Value = &x;
| -- you could clone this value
| - you could clone this value
error: aborting due to 1 previous error

View File

@ -13,9 +13,8 @@ LL | println!("{}", y);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = f(&x, ());
LL + let y = f(x.clone(), ());
|
LL | let y = f(&x.clone(), ());
| ++++++++
error: aborting due to 1 previous error

View File

@ -30,9 +30,8 @@ LL | println!("{}", y);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = f(&x, ());
LL + let y = f(x.clone(), ());
|
LL | let y = f(&x.clone(), ());
| ++++++++
error: aborting due to 2 previous errors

View File

@ -13,9 +13,8 @@ LL | println!("{}", y);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = f(&x, ());
LL + let y = f(x.clone(), ());
|
LL | let y = f(&x.clone(), ());
| ++++++++
error: aborting due to 1 previous error

View File

@ -101,15 +101,6 @@ LL | mut_foo;
| ^^^^^^^ move out of `mut_foo` occurs here
LL | ret;
| --- borrow later used here
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/move-fn-self-receiver.rs:5:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let ret = mut_foo.use_mut_self();
| ------- you could clone this value
error[E0382]: use of moved value: `rc_foo`
--> $DIR/move-fn-self-receiver.rs:55:5

View File

@ -60,9 +60,8 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let r = &x;
LL + let r = x.clone();
|
LL | let r = &x.clone();
| ++++++++
error[E0382]: borrow of moved value: `x`
--> $DIR/closure-access-spans.rs:35:5
@ -109,11 +108,6 @@ LL | || *x = String::new();
| ^^ -- borrow occurs due to use in closure
| |
| value borrowed here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let r = x.clone();
| ++++++++
error[E0382]: use of moved value: `x`
--> $DIR/closure-access-spans.rs:50:5
@ -126,11 +120,6 @@ LL | || x;
| ^^ - use occurs due to use in closure
| |
| value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let r = x.clone();
| ++++++++
error: aborting due to 9 previous errors

View File

@ -10,11 +10,6 @@ LL | _ if { (|| { let bar = b; *bar = false; })();
| -- - variable moved due to use in closure
| |
| value moved into closure here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | _ if { (|| { let bar = b.clone(); *bar = false; })();
| ++++++++
error[E0382]: use of moved value: `b`
--> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
@ -28,11 +23,6 @@ LL | (|| { let bar = b; *bar = false; })();
| -- - variable moved due to use in closure
| |
| value moved into closure here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | (|| { let bar = b.clone(); *bar = false; })();
| ++++++++
error: aborting due to 2 previous errors

View File

@ -1,23 +0,0 @@
// Issue 27282: Example 1: This sidesteps the AST checks disallowing
// mutable borrows in match guards by hiding the mutable borrow in a
// guard behind a move (of the ref mut pattern id) within a closure.
//@ run-rustfix
#![feature(if_let_guard)]
fn main() {
match Some(&4) {
None => {},
ref mut foo
if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo
if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
Some(s) => std::process::exit(*s),
}
}

View File

@ -1,7 +1,7 @@
// Issue 27282: Example 1: This sidesteps the AST checks disallowing
// mutable borrows in match guards by hiding the mutable borrow in a
// guard behind a move (of the ref mut pattern id) within a closure.
//@ run-rustfix
#![feature(if_let_guard)]
fn main() {

View File

@ -7,10 +7,6 @@ LL | if { (|| { let mut bar = foo; bar.take() })(); false } => {},
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
| ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
@ -21,10 +17,6 @@ LL | if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); N
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
| ++++++++
error: aborting due to 2 previous errors

View File

@ -7,10 +7,6 @@ LL | (|| { let bar = foo; bar.take() })();
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | (|| { let bar = foo.clone(); bar.take() })();
| ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-mutation-in-guard.rs:20:18
@ -21,10 +17,6 @@ LL | (|| { let bar = foo; bar.take() })();
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | (|| { let bar = foo.clone(); bar.take() })();
| ++++++++
error: aborting due to 2 previous errors

View File

@ -41,10 +41,6 @@ help: consider borrowing here
|
LL | let p = &s.url; p
| +
help: consider cloning the value if the performance cost is acceptable
|
LL | let p = s.url.clone(); p
| ++++++++
error: aborting due to 4 previous errors

View File

@ -1,66 +0,0 @@
#![feature(if_let_guard)]
#![allow(unused_mut)]
//@ run-rustfix
// Here is arielb1's basic example from rust-lang/rust#27282
// that AST borrowck is flummoxed by:
fn should_reject_destructive_mutate_in_guard() {
match Some(&4) {
None => {},
ref mut foo if {
(|| { let mut bar = foo.clone(); bar.take() })();
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
false } => { },
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo if let Some(()) = {
(|| { let mut bar = foo.clone(); bar.take() })();
//~^ ERROR cannot move out of `foo` in pattern guard [E0507]
None } => { },
Some(s) => std::process::exit(*s),
}
}
// Here below is a case that needs to keep working: we only use the
// binding via immutable-borrow in the guard, and we mutate in the arm
// body.
fn allow_mutate_in_arm_body() {
match Some(&4) {
None => {},
ref mut foo if foo.is_some() => { foo.take(); () }
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
ref mut foo if let Some(_) = foo => { foo.take(); () }
Some(s) => std::process::exit(*s),
}
}
// Here below is a case that needs to keep working: we only use the
// binding via immutable-borrow in the guard, and we move into the arm
// body.
fn allow_move_into_arm_body() {
match Some(&4) {
None => {},
mut foo if foo.is_some() => { foo.unwrap(); () }
Some(s) => std::process::exit(*s),
}
match Some(&4) {
None => {},
mut foo if let Some(_) = foo => { foo.unwrap(); () }
Some(s) => std::process::exit(*s),
}
}
fn main() {
should_reject_destructive_mutate_in_guard();
allow_mutate_in_arm_body();
allow_move_into_arm_body();
}

View File

@ -1,6 +1,5 @@
#![feature(if_let_guard)]
#![allow(unused_mut)]
//@ run-rustfix
// Here is arielb1's basic example from rust-lang/rust#27282
// that AST borrowck is flummoxed by:

View File

@ -1,5 +1,5 @@
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/match-guards-always-borrow.rs:12:14
--> $DIR/match-guards-always-borrow.rs:11:14
|
LL | (|| { let mut bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@ -7,13 +7,9 @@ LL | (|| { let mut bar = foo; bar.take() })();
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | (|| { let mut bar = foo.clone(); bar.take() })();
| ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/match-guards-always-borrow.rs:21:14
--> $DIR/match-guards-always-borrow.rs:20:14
|
LL | (|| { let mut bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@ -21,10 +17,6 @@ LL | (|| { let mut bar = foo; bar.take() })();
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
help: consider cloning the value if the performance cost is acceptable
|
LL | (|| { let mut bar = foo.clone(); bar.take() })();
| ++++++++
error: aborting due to 2 previous errors

View File

@ -27,6 +27,12 @@ LL | let z = x;
| ^ move out of `x` occurs here
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = &mut *x;
LL + let y = &mut x.clone();
|
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/polonius-smoke-test.rs:42:5
@ -40,6 +46,12 @@ LL | s;
| ^ move out of `s` occurs here
LL | tmp;
| --- borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let r = &mut *s;
LL + let r = &mut s.clone();
|
error: aborting due to 4 previous errors

View File

@ -333,14 +333,6 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
note: if `U` implemented `Clone`, you could clone the value
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
|
LL | struct U;
| ^^^^^^^^ consider implementing `Clone` for this type
...
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| - you could clone this value
error[E0507]: cannot move out of `b` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
@ -349,14 +341,6 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
note: if `U` implemented `Clone`, you could clone the value
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
|
LL | struct U;
| ^^^^^^^^ consider implementing `Clone` for this type
...
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| - you could clone this value
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0507]: cannot move out of `a` in pattern guard

View File

@ -15,7 +15,7 @@ LL | *lock.lock().unwrap() = &z;
help: consider cloning the value if the performance cost is acceptable
|
LL - *lock.lock().unwrap() = &*y;
LL + *lock.lock().unwrap() = y.clone();
LL + *lock.lock().unwrap() = &y.clone();
|
error[E0597]: `z` does not live long enough
@ -48,7 +48,7 @@ LL | *lock.write().unwrap() = &z;
help: consider cloning the value if the performance cost is acceptable
|
LL - *lock.write().unwrap() = &*y;
LL + *lock.write().unwrap() = y.clone();
LL + *lock.write().unwrap() = &y.clone();
|
error[E0597]: `z` does not live long enough
@ -81,7 +81,7 @@ LL | tx.send(&z).unwrap();
help: consider cloning the value if the performance cost is acceptable
|
LL - tx.send(&*y);
LL + tx.send(y.clone());
LL + tx.send(&y.clone());
|
error[E0597]: `z` does not live long enough

View File

@ -10,9 +10,8 @@ LL | for j in a {
|
help: consider cloning the value if the performance cost is acceptable
|
LL - for i in &a {
LL + for i in a.clone() {
|
LL | for i in &a.clone() {
| ++++++++
error[E0382]: use of moved value: `a`
--> $DIR/borrow-for-loop-head.rs:4:18

View File

@ -34,11 +34,6 @@ LL | Err(k) ?;
...
LL | ::std::mem::drop(k);
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
LL | Err(k.clone()) ?;
| ++++++++
error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-bad-lifetime.rs:32:9

View File

@ -40,7 +40,7 @@ help: if `T` implemented `Clone`, you could clone the value
LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/unop-move-semantics.rs:17:6
@ -63,7 +63,7 @@ LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
LL | let n = &mut y;
| ------ you could clone this value
| - you could clone this value
error[E0507]: cannot move out of `*m` which is behind a mutable reference
--> $DIR/unop-move-semantics.rs:24:6

View File

@ -17,7 +17,7 @@ LL | struct AffineU32(u32);
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = foo(&a);
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:41:14
@ -38,7 +38,7 @@ LL | struct AffineU32(u32);
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = bar(&a);
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:47:14
@ -59,7 +59,7 @@ LL | struct AffineU32(u32);
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = baz(&a);
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:53:14
@ -80,7 +80,7 @@ LL | struct AffineU32(u32);
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = bat(&a);
| -- you could clone this value
| - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:59:14
@ -96,9 +96,8 @@ LL | drop(x);
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let x = foo(&a);
LL + let x = foo(a.clone());
|
LL | let x = foo(&a.clone());
| ++++++++
error: aborting due to 5 previous errors