mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 14:01:51 +00:00
Suggest .clone()
when moved while borrowed
This commit is contained in:
parent
ccae456863
commit
fa2fc3ab96
@ -987,6 +987,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
can_suggest_clone
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_cloning(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
if let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
|
||||
&& self
|
||||
.infcx
|
||||
.type_implements_trait(clone_trait_def, [ty], self.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
self.suggest_cloning_inner(err, ty, expr, span);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clone_on_reference(&self, expr: &hir::Expr<'_>) -> Option<Span> {
|
||||
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
if let hir::ExprKind::MethodCall(segment, rcvr, args, span) = expr.kind
|
||||
@ -1002,7 +1019,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_cloning(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'_>, span: Span) {
|
||||
fn suggest_cloning_inner(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let suggestion =
|
||||
@ -1136,6 +1159,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
None,
|
||||
);
|
||||
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, borrow_span);
|
||||
}
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
@ -1553,22 +1582,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
for ty in types_to_constrain {
|
||||
self.suggest_adding_bounds(err, ty, clone, body.span);
|
||||
if let ty::Adt(..) = ty.kind() {
|
||||
// The type doesn't implement Clone.
|
||||
let trait_ref = ty::Binder::dummy(ty::TraitRef::new(self.infcx.tcx, clone, [ty]));
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
trait_ref,
|
||||
);
|
||||
self.infcx.err_ctxt().suggest_derive(
|
||||
&obligation,
|
||||
err,
|
||||
trait_ref.to_predicate(self.infcx.tcx),
|
||||
);
|
||||
}
|
||||
self.suggest_adding_bounds_or_derive(err, ty, clone, body.span);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_adding_bounds_or_derive(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
) {
|
||||
self.suggest_adding_bounds(err, ty, def_id, span);
|
||||
if let ty::Adt(..) = ty.kind() {
|
||||
// The type doesn't implement DefId.
|
||||
let trait_ref = ty::Binder::dummy(ty::TraitRef::new(self.infcx.tcx, def_id, [ty]));
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
trait_ref,
|
||||
);
|
||||
self.infcx.err_ctxt().suggest_derive(
|
||||
&obligation,
|
||||
err,
|
||||
trait_ref.to_predicate(self.infcx.tcx),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | drop(x);
|
||||
| ^ move out of `x` occurs here
|
||||
LL | return f(y);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | 's: loop { y = denormalise(&x.clone()); break }
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -51,6 +51,11 @@ LL | x
|
||||
...
|
||||
LL | use_mut(n); use_imm(m);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let m = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `y` because it is borrowed
|
||||
--> $DIR/binop-move-semantics.rs:23:5
|
||||
|
@ -10,6 +10,11 @@ LL | let y = x;
|
||||
LL |
|
||||
LL | r.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
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
|
||||
@ -42,6 +47,11 @@ LL | let y = x;
|
||||
| ^ move out of `x` occurs here
|
||||
LL | r.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
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
|
||||
|
@ -10,6 +10,11 @@ LL | &*a,
|
||||
| --- borrow of `*a` occurs here
|
||||
LL | a);
|
||||
| ^ move out of `a` occurs here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | &*a.clone(),
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `a` because it is borrowed
|
||||
--> $DIR/borrowck-bad-nested-calls-move.rs:32:9
|
||||
@ -22,6 +27,11 @@ LL | &*a,
|
||||
| --- borrow of `*a` occurs here
|
||||
LL | a);
|
||||
| ^ move out of `a` occurs here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | &*a.clone(),
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -49,6 +49,11 @@ LL | drop(x.b);
|
||||
| ^^^ move out of `x.b` occurs here
|
||||
LL | drop(**p);
|
||||
| --- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
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
|
||||
@ -61,6 +66,11 @@ LL | let _y = A { a: 3, .. x };
|
||||
| ^^^^^^^^^^^^^^^^ move out of `x.b` occurs here
|
||||
LL | drop(**p);
|
||||
| --- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
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
|
||||
|
@ -13,6 +13,11 @@ LL | println!("v={}", *v);
|
||||
LL | });
|
||||
LL | w.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
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
|
||||
@ -29,6 +34,11 @@ LL | println!("v={}", *v);
|
||||
LL | });
|
||||
LL | w.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let w = &v.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -9,6 +9,11 @@ LL | take(v);
|
||||
| ^ move out of `v` occurs here
|
||||
LL | w.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let w = &v.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | let z = *a;
|
||||
| ^^ move out of `*a` occurs here
|
||||
LL | b.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let b = &a.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | let t1 = t0;
|
||||
LL | *t1 = 22;
|
||||
LL | p.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let p: &isize = &*t0.clone(); // Freezes `*t0`
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -9,6 +9,11 @@ LL | let S { x: ax } = a;
|
||||
| ^^ move out of `a.x` occurs here
|
||||
LL | f(pb);
|
||||
| -- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let pb = &a.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -14,6 +14,11 @@ LL | drop(x1);
|
||||
...
|
||||
LL | borrow(&*p1);
|
||||
| ---- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let p1 = &x1.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `x2` because it is borrowed
|
||||
--> $DIR/borrowck-multiple-captures.rs:12:19
|
||||
@ -30,6 +35,11 @@ LL | drop(x2);
|
||||
...
|
||||
LL | borrow(&*p2);
|
||||
| ---- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let p2 = &x2.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `x1`
|
||||
--> $DIR/borrowck-multiple-captures.rs:27:19
|
||||
@ -93,6 +103,11 @@ LL | drop(x);
|
||||
...
|
||||
LL | borrow(&*p);
|
||||
| --- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let p = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/borrowck-multiple-captures.rs:52:14
|
||||
|
@ -9,6 +9,11 @@ LL | free(x);
|
||||
| ^ move out of `x` occurs here
|
||||
LL | *y
|
||||
| -- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let y = &*x.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -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;
|
||||
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;
|
||||
let a = &x.clone();
|
||||
let b = a.clone();
|
||||
drop(x);
|
||||
//~^ ERROR cannot move out of `x` because it is borrowed
|
||||
|
@ -36,6 +36,10 @@ help: consider further restricting this bound
|
||||
|
|
||||
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();
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `x` because it is borrowed
|
||||
--> $DIR/clone-on-ref.rs:23:10
|
||||
@ -57,6 +61,10 @@ help: consider annotating `A` with `#[derive(Clone)]`
|
||||
LL + #[derive(Clone)]
|
||||
LL | struct A;
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let a = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -9,6 +9,11 @@ LL | drop(s);
|
||||
| ^ move out of `s` occurs here
|
||||
LL | }
|
||||
| - borrow might be used here, when `_map` is dropped and runs the `Drop` code for type `BTreeMap`
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s.clone()))]);
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -9,6 +9,11 @@ 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
|
||||
|
||||
|
@ -13,6 +13,11 @@ LL | println!("child function: {}", fancy_num.num);
|
||||
...
|
||||
LL | println!("main function: {}", fancy_ref.num);
|
||||
| ------------- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let fancy_ref = &fancy_num.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | eat(x);
|
||||
| ^ move out of `x` occurs here
|
||||
LL | _ref_to_val.use_ref();
|
||||
| ----------- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _ref_to_val: &Value = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | drop(x);
|
||||
LL |
|
||||
LL | println!("{}", y);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let y = f(&x.clone(), ());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -27,6 +27,11 @@ LL | drop(x);
|
||||
| ^ move out of `x` occurs here
|
||||
LL | println!("{}", y);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let y = f(&x.clone(), ());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | drop(x);
|
||||
LL |
|
||||
LL | println!("{}", y);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let y = f(&x.clone(), ());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -57,6 +57,11 @@ LL | || x;
|
||||
| move out of `x` occurs here
|
||||
LL | r.use_ref();
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let r = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/closure-access-spans.rs:35:5
|
||||
|
@ -10,6 +10,11 @@ LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
LL | _x1 = U;
|
||||
LL | drop(hold_all);
|
||||
| -------- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let hold_all = &arr.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0384]: cannot assign twice to immutable variable `_x1`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:9:5
|
||||
|
@ -57,6 +57,11 @@ LL | f(Box::new(|a| {
|
||||
LL |
|
||||
LL | foo(f);
|
||||
| - move occurs due to use in closure
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | f.clone()(Box::new(|a| {
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -11,6 +11,11 @@ LL | drop(y);
|
||||
...
|
||||
LL | *lock.lock().unwrap() = &z;
|
||||
| ---- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | *lock.lock().unwrap() = &*y.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0597]: `z` does not live long enough
|
||||
--> $DIR/send-is-not-static-std-sync.rs:16:33
|
||||
@ -38,6 +43,11 @@ LL | drop(y);
|
||||
...
|
||||
LL | *lock.write().unwrap() = &z;
|
||||
| ---- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | *lock.write().unwrap() = &*y.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0597]: `z` does not live long enough
|
||||
--> $DIR/send-is-not-static-std-sync.rs:30:34
|
||||
@ -65,6 +75,11 @@ LL | drop(y);
|
||||
...
|
||||
LL | tx.send(&z).unwrap();
|
||||
| -- borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | tx.send(&*y.clone());
|
||||
| ++++++++
|
||||
|
||||
error[E0597]: `z` does not live long enough
|
||||
--> $DIR/send-is-not-static-std-sync.rs:46:17
|
||||
|
@ -7,6 +7,11 @@ LL | for i in &a {
|
||||
| -- borrow of `a` occurs here
|
||||
LL | for j in a {
|
||||
| ^ move out of `a` occurs here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | for i in &a.clone() {
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/borrow-for-loop-head.rs:4:18
|
||||
|
@ -33,6 +33,11 @@ LL | !x;
|
||||
...
|
||||
LL | use_mut(n); use_imm(m);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let m = &x.clone();
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `y` because it is borrowed
|
||||
--> $DIR/unop-move-semantics.rs:17:6
|
||||
|
@ -9,6 +9,11 @@ LL | drop(a);
|
||||
| ^ move out of `a` occurs here
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let x = foo(&a.clone());
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `a` because it is borrowed
|
||||
--> $DIR/variance-issue-20533.rs:34:14
|
||||
@ -21,6 +26,11 @@ LL | drop(a);
|
||||
| ^ move out of `a` occurs here
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let x = bar(&a.clone());
|
||||
| ++++++++
|
||||
|
||||
error[E0505]: cannot move out of `a` because it is borrowed
|
||||
--> $DIR/variance-issue-20533.rs:40:14
|
||||
@ -33,6 +43,11 @@ LL | drop(a);
|
||||
| ^ move out of `a` occurs here
|
||||
LL | drop(x);
|
||||
| - borrow later used here
|
||||
|
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let x = baz(&a.clone());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user