Skip to content

Commit 8610edd

Browse files
committed
Suggest deriving required supertraits
1 parent 393fdc1 commit 8610edd

File tree

3 files changed

+126
-4
lines changed

3 files changed

+126
-4
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11961196
Some(adt) if adt.did.is_local() => adt,
11971197
_ => continue,
11981198
};
1199-
let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) {
1199+
let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id());
1200+
let can_derive = match diagnostic_name {
12001201
Some(sym::Default) => !adt.is_enum(),
12011202
Some(
12021203
sym::Eq
@@ -1211,10 +1212,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12111212
_ => false,
12121213
};
12131214
if can_derive {
1215+
let self_name = trait_pred.self_ty().to_string();
1216+
let self_span = self.tcx.def_span(adt.did);
1217+
if let Some(sym::Ord) = diagnostic_name {
1218+
derives.push((self_name.clone(), self_span.clone(), "PartialOrd".to_string()));
1219+
}
1220+
if let Some(sym::Eq) = diagnostic_name {
1221+
derives.push((self_name.clone(), self_span.clone(), "PartialEq".to_string()));
1222+
}
12141223
derives.push((
1215-
format!("{}", trait_pred.self_ty()),
1216-
self.tcx.def_span(adt.did),
1217-
format!("{}", trait_pred.trait_ref.print_only_trait_name()),
1224+
self_name,
1225+
self_span,
1226+
trait_pred.trait_ref.print_only_trait_name().to_string(),
12181227
));
12191228
} else {
12201229
traits.push(self.tcx.def_span(trait_pred.def_id()));

src/test/ui/derives/issue-91550.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::collections::HashSet;
2+
3+
/// natural case from the issue
4+
struct Value(u32);
5+
6+
fn main() {
7+
let hs = HashSet::<Value>::new();
8+
hs.insert(Value(0)); //~ ERROR
9+
}
10+
11+
/// synthetic cases
12+
pub struct NoDerives;
13+
14+
struct Object<T>(T);
15+
impl<T: Eq> Object<T> {
16+
fn use_eq(&self) {}
17+
}
18+
impl<T: Ord> Object<T> {
19+
fn use_ord(&self) {}
20+
}
21+
impl<T: Ord + PartialOrd> Object<T> {
22+
fn use_ord_and_partial_ord(&self) {}
23+
}
24+
25+
fn function(foo: Object<NoDerives>) {
26+
foo.use_eq(); //~ ERROR
27+
foo.use_ord(); //~ ERROR
28+
foo.use_ord_and_partial_ord(); //~ ERROR
29+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
error[E0599]: the method `insert` exists for struct `HashSet<Value>`, but its trait bounds were not satisfied
2+
--> $DIR/issue-91550.rs:8:8
3+
|
4+
LL | struct Value(u32);
5+
| ------------------
6+
| |
7+
| doesn't satisfy `Value: Eq`
8+
| doesn't satisfy `Value: Hash`
9+
...
10+
LL | hs.insert(Value(0));
11+
| ^^^^^^ method cannot be called on `HashSet<Value>` due to unsatisfied trait bounds
12+
|
13+
= note: the following trait bounds were not satisfied:
14+
`Value: Eq`
15+
`Value: Hash`
16+
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
17+
|
18+
LL | #[derive(Eq, Hash, PartialEq)]
19+
|
20+
21+
error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
22+
--> $DIR/issue-91550.rs:26:9
23+
|
24+
LL | pub struct NoDerives;
25+
| --------------------- doesn't satisfy `NoDerives: Eq`
26+
LL |
27+
LL | struct Object<T>(T);
28+
| -------------------- method `use_eq` not found for this
29+
...
30+
LL | foo.use_eq();
31+
| ^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
32+
|
33+
= note: the following trait bounds were not satisfied:
34+
`NoDerives: Eq`
35+
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
36+
|
37+
LL | #[derive(Eq, PartialEq)]
38+
|
39+
40+
error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
41+
--> $DIR/issue-91550.rs:27:9
42+
|
43+
LL | pub struct NoDerives;
44+
| --------------------- doesn't satisfy `NoDerives: Ord`
45+
LL |
46+
LL | struct Object<T>(T);
47+
| -------------------- method `use_ord` not found for this
48+
...
49+
LL | foo.use_ord();
50+
| ^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
51+
|
52+
= note: the following trait bounds were not satisfied:
53+
`NoDerives: Ord`
54+
help: consider annotating `NoDerives` with `#[derive(Ord, PartialOrd)]`
55+
|
56+
LL | #[derive(Ord, PartialOrd)]
57+
|
58+
59+
error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoDerives>`, but its trait bounds were not satisfied
60+
--> $DIR/issue-91550.rs:28:9
61+
|
62+
LL | pub struct NoDerives;
63+
| ---------------------
64+
| |
65+
| doesn't satisfy `NoDerives: Ord`
66+
| doesn't satisfy `NoDerives: PartialOrd`
67+
LL |
68+
LL | struct Object<T>(T);
69+
| -------------------- method `use_ord_and_partial_ord` not found for this
70+
...
71+
LL | foo.use_ord_and_partial_ord();
72+
| ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object<NoDerives>` due to unsatisfied trait bounds
73+
|
74+
= note: the following trait bounds were not satisfied:
75+
`NoDerives: Ord`
76+
`NoDerives: PartialOrd`
77+
help: consider annotating `NoDerives` with `#[derive(Ord, PartialOrd)]`
78+
|
79+
LL | #[derive(Ord, PartialOrd)]
80+
|
81+
82+
error: aborting due to 4 previous errors
83+
84+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)