Skip to content

Commit e1b3401

Browse files
committed
Suggest #[derive(Clone)]
1 parent f194880 commit e1b3401

6 files changed

+44
-7
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_infer::infer;
1414
use rustc_infer::traits::{self, StatementAsExpression};
1515
use rustc_middle::lint::in_external_macro;
1616
use rustc_middle::ty::{
17-
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, Ty,
17+
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
1818
};
1919
use rustc_session::errors::ExprParenthesesNeeded;
2020
use rustc_span::symbol::sym;
@@ -1278,15 +1278,13 @@ 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 trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
12811282
// And the expected type doesn't implement `Clone`
12821283
&& !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
12831284
self.tcx,
12841285
traits::ObligationCause::dummy(),
12851286
self.param_env,
1286-
ty::Binder::dummy(self.tcx.mk_trait_ref(
1287-
clone_trait_did,
1288-
[expected_ty],
1289-
)),
1287+
trait_ref,
12901288
))
12911289
{
12921290
diag.span_note(
@@ -1305,6 +1303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13051303
diag,
13061304
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
13071305
);
1306+
} else {
1307+
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
13081308
}
13091309
}
13101310
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1848,7 +1848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18481848
self.suggest_derive(err, &preds);
18491849
}
18501850

1851-
fn suggest_derive(
1851+
pub fn suggest_derive(
18521852
&self,
18531853
err: &mut Diagnostic,
18541854
unsatisfied_predicates: &[(

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

+8
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

+7
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

+19-1
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

+4
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)