Peel off explicit (or implicit) deref before suggesting clone on move error in borrowck
This commit is contained in:
parent
e7eae5370e
commit
91acacf85b
45 changed files with 111 additions and 351 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue