about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-06-02 12:34:55 -0700
committerEsteban Küber <esteban@kuber.com.ar>2022-06-02 12:54:04 -0700
commit8567b686f9b5f85b18341d77814088a4a7409238 (patch)
tree42faa2c174734f321a7dc2a5ffdb0de0bc327017
parent395a09c3dafe0c7838c9ca41d2b47bb5e79a5b6d (diff)
On E0204 suggest missing type param bounds
```
error[E0204]: the trait `Copy` may not be implemented for this type
  --> f42.rs:9:17
   |
9  | #[derive(Debug, Copy, Clone)]
   |                 ^^^^
10 | pub struct AABB<K>{
11 |     pub loc: Vector2<K>,
   |     ------------------- this field does not implement `Copy`
12 |     pub size: Vector2<K>
   |     -------------------- this field does not implement `Copy`
   |
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
  --> f42.rs:11:5
   |
11 |     pub loc: Vector2<K>,
   |     ^^^^^^^^^^^^^^^^^^^
note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
  --> f42.rs:12:5
   |
12 |     pub size: Vector2<K>
   |     ^^^^^^^^^^^^^^^^^^^^
   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `K`
   |
10 | pub struct AABB<K: Debug>{
   |                  +++++++
```

Fix #89137.
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs5
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs41
-rw-r--r--src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed10
-rw-r--r--src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr10
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed16
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs16
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr19
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed16
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs16
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr30
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs15
-rw-r--r--src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr30
12 files changed, 211 insertions, 13 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 462fc27009d..9bb64d4023b 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -272,7 +272,10 @@ pub fn suggest_constraining_type_params<'a>(
             continue;
         }
 
-        let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
+        let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
+        constraint.sort();
+        constraint.dedup();
+        let constraint = constraint.join(" + ");
         let mut suggest_restrict = |span, bound_list_non_empty| {
             suggestions.push((
                 span,
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index d08d9938708..5953a13506d 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -11,8 +11,7 @@ use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
-use rustc_middle::ty::TypeFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
 use rustc_trait_selection::traits::predicate_for_trait_def;
@@ -91,6 +90,19 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
                 E0204,
                 "the trait `Copy` may not be implemented for this type"
             );
+
+            // We'll try to suggest constraining type parameters to fulfill the requirements of
+            // their `Copy` implementation.
+            let mut generics = None;
+            if let ty::Adt(def, _substs) = self_type.kind() {
+                let self_def_id = def.did();
+                if let Some(local) = self_def_id.as_local() {
+                    let self_item = tcx.hir().expect_item(local);
+                    generics = self_item.kind.generics();
+                }
+            }
+            let mut bounds = vec![];
+
             for (field, ty) in fields {
                 let field_span = tcx.def_span(field.did);
                 err.span_label(field_span, "this field does not implement `Copy`");
@@ -123,9 +135,34 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
                                 ),
                             );
                         }
+                        if let ty::PredicateKind::Trait(ty::TraitPredicate {
+                            trait_ref,
+                            polarity: ty::ImplPolarity::Positive,
+                            ..
+                        }) = error_predicate.kind().skip_binder()
+                        {
+                            let ty = trait_ref.self_ty();
+                            if let ty::Param(_) = ty.kind() {
+                                bounds.push((
+                                    format!("{ty}"),
+                                    trait_ref.print_only_trait_path().to_string(),
+                                    Some(trait_ref.def_id),
+                                ));
+                            }
+                        }
                     }
                 });
             }
+            if let Some(generics) = generics {
+                suggest_constraining_type_params(
+                    tcx,
+                    generics,
+                    &mut err,
+                    bounds.iter().map(|(param, constraint, def_id)| {
+                        (param.as_str(), constraint.as_str(), *def_id)
+                    }),
+                );
+            }
             err.emit();
         }
         Err(CopyImplementationError::NotAnAdt) => {
diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
index ba1b745ba84..45acf5beb12 100644
--- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
+++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed
@@ -21,7 +21,7 @@ fn duplicate_tup2<A: Copy, B: Copy>(t: (A, B)) -> ((A, B), (A, B)) {
     (t, t) //~ use of moved value: `t`
 }
 
-fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
+fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
     //~^ HELP consider restricting type parameter `T`
     (t, t) //~ use of moved value: `t`
 }
@@ -39,14 +39,14 @@ trait A {}
 trait B {}
 
 // Test where bounds are added with different bound placements
-fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
+fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
     //~^ HELP consider restricting type parameter `T`
     (t, t) //~ use of moved value: `t`
 }
 
 fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>)
 where
-    T: A + Trait + Copy,
+    T: A + Copy + Trait,
     //~^ HELP consider further restricting this bound
 {
     (t, t) //~ use of moved value: `t`
@@ -54,14 +54,14 @@ where
 
 fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>)
 where
-    T: A + Trait + Copy,
+    T: A + Copy + Trait,
     //~^ HELP consider further restricting this bound
     T: B,
 {
     (t, t) //~ use of moved value: `t`
 }
 
-fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
+fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
 //~^ HELP consider further restricting this bound
 where
     T: B,
diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
index 2353cd079a3..5a84e3b81a6 100644
--- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
+++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr
@@ -75,7 +75,7 @@ LL |     (t, t)
    |
 help: consider restricting type parameter `T`
    |
-LL | fn duplicate_custom<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) {
+LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) {
    |                      ++++++++++++++
 
 error[E0382]: use of moved value: `t`
@@ -91,7 +91,7 @@ LL |     (t, t)
    |
 help: consider restricting type parameter `T`
    |
-LL | fn duplicate_custom_1<T: Trait + Copy>(t: S<T>) -> (S<T>, S<T>) where {
+LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where {
    |                        ++++++++++++++
 
 error[E0382]: use of moved value: `t`
@@ -107,7 +107,7 @@ LL |     (t, t)
    |
 help: consider further restricting this bound
    |
-LL |     T: A + Trait + Copy,
+LL |     T: A + Copy + Trait,
    |          ++++++++++++++
 
 error[E0382]: use of moved value: `t`
@@ -123,7 +123,7 @@ LL |     (t, t)
    |
 help: consider further restricting this bound
    |
-LL |     T: A + Trait + Copy,
+LL |     T: A + Copy + Trait,
    |          ++++++++++++++
 
 error[E0382]: use of moved value: `t`
@@ -139,7 +139,7 @@ LL |     (t, t)
    |
 help: consider further restricting this bound
    |
-LL | fn duplicate_custom_4<T: A + Trait + Copy>(t: S<T>) -> (S<T>, S<T>)
+LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>)
    |                            ++++++++++++++
 
 error[E0382]: use of moved value: `t`
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
new file mode 100644
index 00000000000..ac0b14fba83
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+    pub x: T,
+    pub y: T
+}
+
+#[derive(Debug, Copy, Clone)]
+pub struct AABB<K: Debug + std::marker::Copy>{
+    pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
+    pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs
new file mode 100644
index 00000000000..31f8cd6fcf7
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+    pub x: T,
+    pub y: T
+}
+
+#[derive(Debug, Copy, Clone)]
+pub struct AABB<K: Debug>{
+    pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
+    pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
new file mode 100644
index 00000000000..03082be690f
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `K: Copy` is not satisfied
+  --> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14
+   |
+LL |     pub loc: Vector2<K>,
+   |              ^^^^^^^^^^ the trait `Copy` is not implemented for `K`
+   |
+note: required by a bound in `Vector2`
+  --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31
+   |
+LL | pub struct Vector2<T: Debug + Copy + Clone>{
+   |                               ^^^^ required by this bound in `Vector2`
+help: consider further restricting this bound
+   |
+LL | pub struct AABB<K: Debug + std::marker::Copy>{
+   |                          +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
new file mode 100644
index 00000000000..304360d48a2
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed
@@ -0,0 +1,16 @@
+//run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+    pub x: T,
+    pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K: Copy + Debug>{
+    pub loc: Vector2<K>,
+    pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs
new file mode 100644
index 00000000000..14e1fbb3311
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs
@@ -0,0 +1,16 @@
+//run-rustfix
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+    pub x: T,
+    pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K: Copy>{
+    pub loc: Vector2<K>,
+    pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
new file mode 100644
index 00000000000..2dc41709fdc
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr
@@ -0,0 +1,30 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17
+   |
+LL | #[derive(Debug, Copy, Clone)]
+   |                 ^^^^
+LL | pub struct AABB<K: Copy>{
+LL |     pub loc: Vector2<K>,
+   |     ------------------- this field does not implement `Copy`
+LL |     pub size: Vector2<K>
+   |     -------------------- this field does not implement `Copy`
+   |
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+  --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:5
+   |
+LL |     pub loc: Vector2<K>,
+   |     ^^^^^^^^^^^^^^^^^^^
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+  --> $DIR/missing-bound-in-derive-copy-impl-3.rs:13:5
+   |
+LL |     pub size: Vector2<K>
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting this bound
+   |
+LL | pub struct AABB<K: Copy + Debug>{
+   |                         +++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs
new file mode 100644
index 00000000000..52163bddd4f
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs
@@ -0,0 +1,15 @@
+use std::fmt::Debug;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Vector2<T: Debug + Copy + Clone>{
+    pub x: T,
+    pub y: T
+}
+
+#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type
+pub struct AABB<K>{
+    pub loc: Vector2<K>,
+    pub size: Vector2<K>
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
new file mode 100644
index 00000000000..1f6932b1fa6
--- /dev/null
+++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
@@ -0,0 +1,30 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17
+   |
+LL | #[derive(Debug, Copy, Clone)]
+   |                 ^^^^
+LL | pub struct AABB<K>{
+LL |     pub loc: Vector2<K>,
+   |     ------------------- this field does not implement `Copy`
+LL |     pub size: Vector2<K>
+   |     -------------------- this field does not implement `Copy`
+   |
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+  --> $DIR/missing-bound-in-derive-copy-impl.rs:11:5
+   |
+LL |     pub loc: Vector2<K>,
+   |     ^^^^^^^^^^^^^^^^^^^
+note: the `Copy` impl for `Vector2<K>` requires that `K: Debug`
+  --> $DIR/missing-bound-in-derive-copy-impl.rs:12:5
+   |
+LL |     pub size: Vector2<K>
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `K`
+   |
+LL | pub struct AABB<K: Debug>{
+   |                  +++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0204`.