Suggest deriving required supertraits
This commit is contained in:
parent
393fdc1048
commit
8610edd014
3 changed files with 126 additions and 4 deletions
|
|
@ -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()));
|
||||
|
|
|
|||
29
src/test/ui/derives/issue-91550.rs
Normal file
29
src/test/ui/derives/issue-91550.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
84
src/test/ui/derives/issue-91550.stderr
Normal file
84
src/test/ui/derives/issue-91550.stderr
Normal file
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue