Skip to content

Commit 0fb8d84

Browse files
committed
Suggest #[derive(Clone)]
1 parent bc92321 commit 0fb8d84

6 files changed

+48
-8
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,17 +1278,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12781278
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
12791279
// Check that we're in fact trying to clone into the expected type
12801280
&& self.can_coerce(*pointee_ty, expected_ty)
1281+
&& let predicate = ty::Binder::dummy(ty::TraitRef {
1282+
def_id: clone_trait_did,
1283+
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
1284+
})
1285+
.without_const()
1286+
.to_predicate(self.tcx)
12811287
// And the expected type doesn't implement `Clone`
12821288
&& !self.predicate_must_hold_considering_regions(&traits::Obligation {
12831289
cause: traits::ObligationCause::dummy(),
12841290
param_env: self.param_env,
12851291
recursion_depth: 0,
1286-
predicate: ty::Binder::dummy(ty::TraitRef {
1287-
def_id: clone_trait_did,
1288-
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
1289-
})
1290-
.without_const()
1291-
.to_predicate(self.tcx),
1292+
predicate,
12921293
})
12931294
{
12941295
diag.span_note(
@@ -1307,6 +1308,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13071308
diag,
13081309
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
13091310
);
1311+
} else {
1312+
self.suggest_derive(diag, &[(predicate, None, None)]);
13101313
}
13111314
}
13121315
}

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18431843
self.suggest_derive(err, &preds);
18441844
}
18451845

1846-
fn suggest_derive(
1846+
pub fn suggest_derive(
18471847
&self,
18481848
err: &mut Diagnostic,
18491849
unsatisfied_predicates: &[(

src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ fn wat<T: Clone>(t: &T) -> T {
33
t.clone() //~ ERROR E0308
44
}
55

6+
#[derive(Clone)]
7+
struct Foo;
8+
9+
fn wut(t: &Foo) -> Foo {
10+
t.clone() //~ ERROR E0308
11+
}
12+
613
fn main() {
714
wat(&42);
15+
wut(&Foo);
816
}

src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ fn wat<T>(t: &T) -> T {
33
t.clone() //~ ERROR E0308
44
}
55

6+
struct Foo;
7+
8+
fn wut(t: &Foo) -> Foo {
9+
t.clone() //~ ERROR E0308
10+
}
11+
612
fn main() {
713
wat(&42);
14+
wut(&Foo);
815
}

src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@ help: consider restricting type parameter `T`
2020
LL | fn wat<T: Clone>(t: &T) -> T {
2121
| +++++++
2222

23-
error: aborting due to previous error
23+
error[E0308]: mismatched types
24+
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
25+
|
26+
LL | fn wut(t: &Foo) -> Foo {
27+
| --- expected `Foo` because of return type
28+
LL | t.clone()
29+
| ^^^^^^^^^ expected struct `Foo`, found `&Foo`
30+
|
31+
note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
32+
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
33+
|
34+
LL | t.clone()
35+
| ^
36+
help: consider annotating `Foo` with `#[derive(Clone)]`
37+
|
38+
LL | #[derive(Clone)]
39+
|
40+
41+
error: aborting due to 2 previous errors
2442

2543
For more information about this error, try `rustc --explain E0308`.

src/test/ui/typeck/explain_clone_autoref.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
1212
|
1313
LL | nc.clone()
1414
| ^^
15+
help: consider annotating `NotClone` with `#[derive(Clone)]`
16+
|
17+
LL | #[derive(Clone)]
18+
|
1519

1620
error: aborting due to previous error
1721

0 commit comments

Comments
 (0)