about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs33
-rw-r--r--src/test/ui/derives/issue-91492.rs25
-rw-r--r--src/test/ui/derives/issue-91492.stderr54
3 files changed, 96 insertions, 16 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index d5a4de86d4d..f3a5fbbb444 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1195,11 +1195,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_derive(
         &self,
         err: &mut DiagnosticBuilder<'_>,
-        unsatisfied_predicates: &Vec<(
+        unsatisfied_predicates: &[(
             ty::Predicate<'tcx>,
             Option<ty::Predicate<'tcx>>,
             Option<ObligationCause<'tcx>>,
-        )>,
+        )],
     ) {
         let mut derives = Vec::<(String, Span, String)>::new();
         let mut traits = Vec::<Span>::new();
@@ -1236,23 +1236,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 traits.push(self.tcx.def_span(trait_pred.def_id()));
             }
         }
-        derives.sort();
-        let derives_grouped = derives.into_iter().fold(
-            Vec::<(String, Span, String)>::new(),
-            |mut acc, (self_name, self_span, trait_name)| {
-                if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
-                    if acc_self_name == &self_name {
-                        traits.push_str(format!(", {}", trait_name).as_str());
-                        return acc;
-                    }
-                }
-                acc.push((self_name, self_span, trait_name));
-                acc
-            },
-        );
         traits.sort();
         traits.dedup();
 
+        derives.sort();
+        derives.dedup();
+
+        let mut derives_grouped = Vec::<(String, Span, String)>::new();
+        for (self_name, self_span, trait_name) in derives.into_iter() {
+            if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut()
+            {
+                if last_self_name == &self_name {
+                    last_trait_names.push_str(format!(", {}", trait_name).as_str());
+                    continue;
+                }
+            }
+            derives_grouped.push((self_name, self_span, trait_name));
+        }
+
         let len = traits.len();
         if len > 0 {
             let span: MultiSpan = traits.into();
diff --git a/src/test/ui/derives/issue-91492.rs b/src/test/ui/derives/issue-91492.rs
new file mode 100644
index 00000000000..df792f118ab
--- /dev/null
+++ b/src/test/ui/derives/issue-91492.rs
@@ -0,0 +1,25 @@
+// Reproduce the issue with vec
+pub struct NoDerives;
+fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) {
+    foo.extend_from_slice(bar); //~ ERROR
+}
+
+// Reproduce the issue with vec
+// and demonstrate that other derives are ignored in the suggested output
+#[derive(Default, PartialEq)]
+pub struct SomeDerives;
+fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) {
+    foo.extend_from_slice(bar); //~ ERROR
+}
+
+// Try and fail to reproduce the issue without vec.
+// No idea why it doesnt reproduce the issue but its still a useful test case.
+struct Object<T, A>(T, A);
+impl<T: Clone, A: Default> Object<T, A> {
+    fn use_clone(&self) {}
+}
+fn fun3(foo: Object<NoDerives, SomeDerives>) {
+    foo.use_clone(); //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/derives/issue-91492.stderr b/src/test/ui/derives/issue-91492.stderr
new file mode 100644
index 00000000000..73c91154a7b
--- /dev/null
+++ b/src/test/ui/derives/issue-91492.stderr
@@ -0,0 +1,54 @@
+error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<NoDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91492.rs:4:9
+   |
+LL | pub struct NoDerives;
+   | --------------------- doesn't satisfy `NoDerives: Clone`
+LL | fn fun1(foo: &mut Vec<NoDerives>, bar: &[NoDerives]) {
+LL |     foo.extend_from_slice(bar);
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: Clone`
+help: consider annotating `NoDerives` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec<SomeDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91492.rs:12:9
+   |
+LL | pub struct SomeDerives;
+   | ----------------------- doesn't satisfy `SomeDerives: Clone`
+LL | fn fun2(foo: &mut Vec<SomeDerives>, bar: &[SomeDerives]) {
+LL |     foo.extend_from_slice(bar);
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: the following trait bounds were not satisfied:
+           `SomeDerives: Clone`
+help: consider annotating `SomeDerives` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error[E0599]: the method `use_clone` exists for struct `Object<NoDerives, SomeDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91492.rs:22:9
+   |
+LL | pub struct NoDerives;
+   | --------------------- doesn't satisfy `NoDerives: Clone`
+...
+LL | struct Object<T, A>(T, A);
+   | -------------------------- method `use_clone` not found for this
+...
+LL |     foo.use_clone();
+   |         ^^^^^^^^^ method cannot be called on `Object<NoDerives, SomeDerives>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: Clone`
+help: consider annotating `NoDerives` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.