Account for unops when suggesting cloning

This commit is contained in:
Esteban Küber 2024-03-13 02:13:51 +00:00
parent fa2fc3ab96
commit bce78102c3
27 changed files with 134 additions and 93 deletions

View File

@ -1034,27 +1034,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
".clone()".to_owned()
};
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
&& self
.infcx
.type_implements_trait(clone_trait_def, [ty], self.param_env)
.must_apply_modulo_regions()
let mut sugg = Vec::with_capacity(2);
let mut inner_expr = expr;
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
&inner_expr.kind
{
let msg = if let ty::Adt(def, _) = ty.kind()
&& [tcx.get_diagnostic_item(sym::Arc), tcx.get_diagnostic_item(sym::Rc)]
.contains(&Some(def.did()))
{
"clone the value to increment its reference count"
} else {
"consider cloning the value if the performance cost is acceptable"
};
err.span_suggestion_verbose(
span.shrink_to_hi(),
msg,
suggestion,
Applicability::MachineApplicable,
);
inner_expr = inner;
}
if inner_expr.span.lo() != expr.span.lo() {
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
}
let span = if inner_expr.span.hi() != expr.span.hi() {
// Account for `(*x)` to suggest `x.clone()`.
expr.span.with_lo(inner_expr.span.hi())
} else {
span.shrink_to_hi()
};
sugg.push((span, suggestion));
let msg = if let ty::Adt(def, _) = ty.kind()
&& [tcx.get_diagnostic_item(sym::Arc), tcx.get_diagnostic_item(sym::Rc)]
.contains(&Some(def.did()))
{
"clone the value to increment its reference count"
} else {
"consider cloning the value if the performance cost is acceptable"
};
err.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
}
fn suggest_adding_bounds(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, def_id: DefId, span: Span) {

View File

@ -13,8 +13,9 @@ LL | return f(y);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | 's: loop { y = denormalise(&x.clone()); break }
| ++++++++
LL - 's: loop { y = denormalise(&x); break }
LL + 's: loop { y = denormalise(x.clone()); break }
|
error: aborting due to 1 previous error

View File

@ -54,8 +54,9 @@ LL | use_mut(n); use_imm(m);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let m = &x.clone();
| ++++++++
LL - let m = &x;
LL + let m = x.clone();
|
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/binop-move-semantics.rs:23:5

View File

@ -13,8 +13,9 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let r = &x.0.clone();
| ++++++++
LL - let r = &x.0;
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
@ -50,8 +51,9 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let r = &x.0.clone();
| ++++++++
LL - let r = &x.0;
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

@ -13,8 +13,9 @@ LL | a);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | &*a.clone(),
| ++++++++
LL - &*a,
LL + a.clone(),
|
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/borrowck-bad-nested-calls-move.rs:32:9
@ -30,8 +31,9 @@ LL | a);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | &*a.clone(),
| ++++++++
LL - &*a,
LL + a.clone(),
|
error: aborting due to 2 previous errors

View File

@ -52,8 +52,9 @@ LL | drop(**p);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let p = &x.b.clone();
| ++++++++
LL - let p = &x.b;
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
@ -69,8 +70,9 @@ LL | drop(**p);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let p = &x.b.clone();
| ++++++++
LL - let p = &x.b;
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

@ -16,8 +16,9 @@ LL | w.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let w = &v.clone();
| ++++++++
LL - let w = &v;
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
@ -37,8 +38,9 @@ LL | w.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let w = &v.clone();
| ++++++++
LL - let w = &v;
LL + let w = v.clone();
|
error: aborting due to 2 previous errors

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ fn foo<T: Default + Clone>(list: &mut Vec<T>) {
drop(cloned_items);
}
fn bar<T: std::fmt::Display + Clone>(x: T) {
let a = &x.clone();
let a = x.clone();
let b = a.clone();
drop(x);
//~^ ERROR cannot move out of `x` because it is borrowed
@ -19,7 +19,7 @@ fn bar<T: std::fmt::Display + Clone>(x: T) {
#[derive(Clone)]
struct A;
fn qux(x: A) {
let a = &x.clone();
let a = x.clone();
let b = a.clone();
drop(x);
//~^ ERROR cannot move out of `x` because it is borrowed

View File

@ -38,8 +38,9 @@ LL | fn bar<T: std::fmt::Display + Clone>(x: T) {
| +++++++
help: consider cloning the value if the performance cost is acceptable
|
LL | let a = &x.clone();
| ++++++++
LL - let a = &x;
LL + let a = x.clone();
|
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/clone-on-ref.rs:23:10
@ -63,8 +64,9 @@ LL | struct A;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let a = &x.clone();
| ++++++++
LL - let a = &x;
LL + let a = x.clone();
|
error: aborting due to 3 previous errors

View File

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

View File

@ -16,8 +16,9 @@ LL | println!("main function: {}", fancy_ref.num);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let fancy_ref = &fancy_num.clone();
| ++++++++
LL - let fancy_ref = &fancy_num;
LL + let fancy_ref = fancy_num.clone();
|
error: aborting due to 1 previous error

View File

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

View File

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

View File

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

View File

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

View File

@ -60,8 +60,9 @@ LL | r.use_ref();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let r = &x.clone();
| ++++++++
LL - let r = &x;
LL + let r = x.clone();
|
error[E0382]: borrow of moved value: `x`
--> $DIR/closure-access-spans.rs:35:5

View File

@ -13,8 +13,9 @@ LL | drop(hold_all);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let hold_all = &arr.clone();
| ++++++++
LL - let hold_all = &arr;
LL + let hold_all = arr.clone();
|
error[E0384]: cannot assign twice to immutable variable `_x1`
--> $DIR/borrowck-move-ref-pattern.rs:9:5

View File

@ -14,8 +14,9 @@ LL | *lock.lock().unwrap() = &z;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | *lock.lock().unwrap() = &*y.clone();
| ++++++++
LL - *lock.lock().unwrap() = &*y;
LL + *lock.lock().unwrap() = y.clone();
|
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:16:33
@ -46,8 +47,9 @@ LL | *lock.write().unwrap() = &z;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | *lock.write().unwrap() = &*y.clone();
| ++++++++
LL - *lock.write().unwrap() = &*y;
LL + *lock.write().unwrap() = y.clone();
|
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:30:34
@ -78,8 +80,9 @@ LL | tx.send(&z).unwrap();
|
help: consider cloning the value if the performance cost is acceptable
|
LL | tx.send(&*y.clone());
| ++++++++
LL - tx.send(&*y);
LL + tx.send(y.clone());
|
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:46:17

View File

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

View File

@ -36,8 +36,9 @@ LL | use_mut(n); use_imm(m);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let m = &x.clone();
| ++++++++
LL - let m = &x;
LL + let m = x.clone();
|
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/unop-move-semantics.rs:17:6

View File

@ -12,8 +12,9 @@ LL | drop(x);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let x = foo(&a.clone());
| ++++++++
LL - let x = foo(&a);
LL + let x = foo(a.clone());
|
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:34:14
@ -29,8 +30,9 @@ LL | drop(x);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let x = bar(&a.clone());
| ++++++++
LL - let x = bar(&a);
LL + let x = bar(a.clone());
|
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:40:14
@ -46,8 +48,9 @@ LL | drop(x);
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let x = baz(&a.clone());
| ++++++++
LL - let x = baz(&a);
LL + let x = baz(a.clone());
|
error: aborting due to 3 previous errors