Skip to content

Commit 9e17ad1

Browse files
committed
Account for assign binops in clone suggestions
Explicitly look for `expr += other_expr;` and avoid suggesting `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
1 parent 32be523 commit 9e17ad1

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,9 +981,39 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
981981
&self,
982982
err: &mut Diag<'_>,
983983
ty: Ty<'tcx>,
984-
expr: &hir::Expr<'_>,
985-
other_expr: Option<&hir::Expr<'_>>,
984+
mut expr: &'cx hir::Expr<'cx>,
985+
mut other_expr: Option<&'cx hir::Expr<'cx>>,
986986
) {
987+
if let Some(some_other_expr) = other_expr
988+
&& let Some(parent_binop) =
989+
self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
990+
if let (hir_id, hir::Node::Expr(e)) = n
991+
&& let hir::ExprKind::AssignOp(_binop, target, _arg) = e.kind
992+
&& target.hir_id == expr.hir_id
993+
{
994+
Some(hir_id)
995+
} else {
996+
None
997+
}
998+
})
999+
&& let Some(other_parent_binop) =
1000+
self.infcx.tcx.hir().parent_iter(some_other_expr.hir_id).find_map(|n| {
1001+
if let (hir_id, hir::Node::Expr(expr)) = n
1002+
&& let hir::ExprKind::AssignOp(..) = expr.kind
1003+
{
1004+
Some(hir_id)
1005+
} else {
1006+
None
1007+
}
1008+
})
1009+
&& { true }
1010+
&& parent_binop == other_parent_binop
1011+
{
1012+
// Explicitly look for `expr += other_expr;` and avoid suggesting
1013+
// `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
1014+
other_expr = Some(expr);
1015+
expr = some_other_expr;
1016+
}
9871017
'outer: {
9881018
if let ty::Ref(..) = ty.kind() {
9891019
// We check for either `let binding = foo(expr, other_expr);` or

tests/ui/augmented-assignments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ fn main() {
1313
let mut x = Int(1); //~ NOTE binding `x` declared here
1414
x
1515
//~^ NOTE borrow of `x` occurs here
16-
//~| HELP consider cloning
1716
+=
1817
x;
1918
//~^ ERROR cannot move out of `x` because it is borrowed
2019
//~| move out of `x` occurs here
20+
//~| HELP consider cloning
2121

2222
let y = Int(2);
2323
//~^ HELP consider changing this to be mutable

tests/ui/augmented-assignments.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | x;
1111
|
1212
help: consider cloning the value if the performance cost is acceptable
1313
|
14-
LL | x.clone()
14+
LL | x.clone();
1515
| ++++++++
1616

1717
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable

0 commit comments

Comments
 (0)