about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-12-13 19:52:42 -0800
committerEsteban Küber <esteban@kuber.com.ar>2022-12-15 10:27:05 -0800
commite1b340195a04bc079df3bda8e627ad6e64938d50 (patch)
treea77d10cee9c68437e4dfda5fa76f09c4474ced7e
parentf19488064a4752703fde8a3596a9d90ca2095534 (diff)
Suggest `#[derive(Clone)]`
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed8
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs7
-rw-r--r--src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr20
-rw-r--r--src/test/ui/typeck/explain_clone_autoref.stderr4
6 files changed, 44 insertions, 7 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 08ef2484776..407d6ac8544 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -14,7 +14,7 @@ use rustc_infer::infer;
 use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, Ty,
+    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::symbol::sym;
@@ -1278,15 +1278,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
             // Check that we're in fact trying to clone into the expected type
             && self.can_coerce(*pointee_ty, expected_ty)
+            && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
             // And the expected type doesn't implement `Clone`
             && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
                 self.tcx,
                 traits::ObligationCause::dummy(),
                 self.param_env,
-                ty::Binder::dummy(self.tcx.mk_trait_ref(
-                    clone_trait_did,
-                    [expected_ty],
-                )),
+                trait_ref,
             ))
         {
             diag.span_note(
@@ -1305,6 +1303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     diag,
                     vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
                 );
+            } else {
+                self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 5c0d5f32f0f..6b3cc26fd76 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1848,7 +1848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.suggest_derive(err, &preds);
     }
 
-    fn suggest_derive(
+    pub fn suggest_derive(
         &self,
         err: &mut Diagnostic,
         unsatisfied_predicates: &[(
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
index 3e5ded6738b..4f9e93a47ed 100644
--- a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
@@ -3,6 +3,14 @@ fn wat<T: Clone>(t: &T) -> T {
     t.clone() //~ ERROR E0308
 }
 
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
 fn main() {
     wat(&42);
+    wut(&Foo);
 }
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
index 1a5a38369ec..89b077d671a 100644
--- a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
@@ -3,6 +3,13 @@ fn wat<T>(t: &T) -> T {
     t.clone() //~ ERROR E0308
 }
 
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
 fn main() {
     wat(&42);
+    wut(&Foo);
 }
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
index 01246955fae..26ab515d9b4 100644
--- a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
+++ b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -20,6 +20,24 @@ help: consider restricting type parameter `T`
 LL | fn wat<T: Clone>(t: &T) -> T {
    |         +++++++
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL | fn wut(t: &Foo) -> Foo {
+   |                    --- expected `Foo` because of return type
+LL |     t.clone()
+   |     ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+   |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/explain_clone_autoref.stderr b/src/test/ui/typeck/explain_clone_autoref.stderr
index faac680ea19..ff36e18d283 100644
--- a/src/test/ui/typeck/explain_clone_autoref.stderr
+++ b/src/test/ui/typeck/explain_clone_autoref.stderr
@@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
    |
 LL |     nc.clone()
    |     ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error