about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs17
-rw-r--r--src/test/ui/derives/issue-91550.rs29
-rw-r--r--src/test/ui/derives/issue-91550.stderr84
3 files changed, 126 insertions, 4 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 81e2b3bc162..5b06cc33302 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1196,7 +1196,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(adt) if adt.did.is_local() => adt,
                 _ => continue,
             };
-            let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) {
+            let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id());
+            let can_derive = match diagnostic_name {
                 Some(sym::Default) => !adt.is_enum(),
                 Some(
                     sym::Eq
@@ -1211,10 +1212,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => false,
             };
             if can_derive {
+                let self_name = trait_pred.self_ty().to_string();
+                let self_span = self.tcx.def_span(adt.did);
+                if let Some(sym::Ord) = diagnostic_name {
+                    derives.push((self_name.clone(), self_span.clone(), "PartialOrd".to_string()));
+                }
+                if let Some(sym::Eq) = diagnostic_name {
+                    derives.push((self_name.clone(), self_span.clone(), "PartialEq".to_string()));
+                }
                 derives.push((
-                    format!("{}", trait_pred.self_ty()),
-                    self.tcx.def_span(adt.did),
-                    format!("{}", trait_pred.trait_ref.print_only_trait_name()),
+                    self_name,
+                    self_span,
+                    trait_pred.trait_ref.print_only_trait_name().to_string(),
                 ));
             } else {
                 traits.push(self.tcx.def_span(trait_pred.def_id()));
diff --git a/src/test/ui/derives/issue-91550.rs b/src/test/ui/derives/issue-91550.rs
new file mode 100644
index 00000000000..56fd5ffa89e
--- /dev/null
+++ b/src/test/ui/derives/issue-91550.rs
@@ -0,0 +1,29 @@
+use std::collections::HashSet;
+
+/// natural case from the issue
+struct Value(u32);
+
+fn main() {
+    let hs = HashSet::<Value>::new();
+    hs.insert(Value(0)); //~ ERROR
+}
+
+/// synthetic cases
+pub struct NoDerives;
+
+struct Object<T>(T);
+impl<T: Eq> Object<T> {
+    fn use_eq(&self) {}
+}
+impl<T: Ord> Object<T> {
+    fn use_ord(&self) {}
+}
+impl<T: Ord + PartialOrd> Object<T> {
+    fn use_ord_and_partial_ord(&self) {}
+}
+
+fn function(foo: Object<NoDerives>) {
+    foo.use_eq(); //~ ERROR
+    foo.use_ord(); //~ ERROR
+    foo.use_ord_and_partial_ord(); //~ ERROR
+}
diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr
new file mode 100644
index 00000000000..2b88c35c6a3
--- /dev/null
+++ b/src/test/ui/derives/issue-91550.stderr
@@ -0,0 +1,84 @@
+error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91550.rs:8:8
+   |
+LL | struct Value(u32);
+   | ------------------
+   | |
+   | doesn't satisfy `Value: Eq`
+   | doesn't satisfy `Value: Hash`
+...
+LL |     hs.insert(Value(0));
+   |        ^^^^^^ method cannot be called on `HashSet<Value>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `Value: Eq`
+           `Value: Hash`
+help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
+   |
+LL | #[derive(Eq, Hash, PartialEq)]
+   |
+
+error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91550.rs:26:9
+   |
+LL | pub struct NoDerives;
+   | --------------------- doesn't satisfy `NoDerives: Eq`
+LL | 
+LL | struct Object<T>(T);
+   | -------------------- method `use_eq` not found for this
+...
+LL |     foo.use_eq();
+   |         ^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: Eq`
+help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
+   |
+LL | #[derive(Eq, PartialEq)]
+   |
+
+error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91550.rs:27:9
+   |
+LL | pub struct NoDerives;
+   | --------------------- doesn't satisfy `NoDerives: Ord`
+LL | 
+LL | struct Object<T>(T);
+   | -------------------- method `use_ord` not found for this
+...
+LL |     foo.use_ord();
+   |         ^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: Ord`
+help: consider annotating `NoDerives` with `#[derive(Ord, PartialOrd)]`
+   |
+LL | #[derive(Ord, PartialOrd)]
+   |
+
+error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
+  --> $DIR/issue-91550.rs:28:9
+   |
+LL | pub struct NoDerives;
+   | ---------------------
+   | |
+   | doesn't satisfy `NoDerives: Ord`
+   | doesn't satisfy `NoDerives: PartialOrd`
+LL | 
+LL | struct Object<T>(T);
+   | -------------------- method `use_ord_and_partial_ord` not found for this
+...
+LL |     foo.use_ord_and_partial_ord();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: Ord`
+           `NoDerives: PartialOrd`
+help: consider annotating `NoDerives` with `#[derive(Ord, PartialOrd)]`
+   |
+LL | #[derive(Ord, PartialOrd)]
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.