Rollup merge of #93693 - rukai:91550, r=davidtwco
Suggest deriving required supertraits closes https://github.com/rust-lang/rust/issues/91550 I chose to just hardcode handling for PartialOrd and PartialEq because that should be robust enough and I dont know how to go about doing it generically r? rust-lang/diagnostics
This commit is contained in:
commit
351aa1b5da
6 changed files with 154 additions and 25 deletions
|
@ -9,8 +9,10 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{ExprKind, Node, QPath};
|
use rustc_hir::{ExprKind, Node, QPath};
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
|
use rustc_middle::traits::util::supertraits;
|
||||||
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
|
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
|
||||||
use rustc_middle::ty::print::with_crate_prefix;
|
use rustc_middle::ty::print::with_crate_prefix;
|
||||||
|
use rustc_middle::ty::ToPolyTraitRef;
|
||||||
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_span::lev_distance;
|
use rustc_span::lev_distance;
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
|
@ -1196,9 +1198,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Some(adt) if adt.did.is_local() => adt,
|
Some(adt) if adt.did.is_local() => adt,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) {
|
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
|
||||||
Some(sym::Default) => !adt.is_enum(),
|
let can_derive = match diagnostic_name {
|
||||||
Some(
|
sym::Default => !adt.is_enum(),
|
||||||
sym::Eq
|
sym::Eq
|
||||||
| sym::PartialEq
|
| sym::PartialEq
|
||||||
| sym::Ord
|
| sym::Ord
|
||||||
|
@ -1206,16 +1208,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
| sym::Clone
|
| sym::Clone
|
||||||
| sym::Copy
|
| sym::Copy
|
||||||
| sym::Hash
|
| sym::Hash
|
||||||
| sym::Debug,
|
| sym::Debug => true,
|
||||||
) => true,
|
_ => false,
|
||||||
_ => false,
|
};
|
||||||
};
|
if can_derive {
|
||||||
if can_derive {
|
let self_name = trait_pred.self_ty().to_string();
|
||||||
derives.push((
|
let self_span = self.tcx.def_span(adt.did);
|
||||||
format!("{}", trait_pred.self_ty()),
|
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
|
||||||
self.tcx.def_span(adt.did),
|
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
|
||||||
format!("{}", trait_pred.trait_ref.print_only_trait_name()),
|
{
|
||||||
));
|
if let Some(parent_diagnostic_name) =
|
||||||
|
self.tcx.get_diagnostic_name(super_trait.def_id())
|
||||||
|
{
|
||||||
|
derives.push((
|
||||||
|
self_name.clone(),
|
||||||
|
self_span.clone(),
|
||||||
|
parent_diagnostic_name.to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
derives.push((self_name, self_span, diagnostic_name.to_string()));
|
||||||
|
} else {
|
||||||
|
traits.push(self.tcx.def_span(trait_pred.def_id()));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
traits.push(self.tcx.def_span(trait_pred.def_id()));
|
traits.push(self.tcx.def_span(trait_pred.def_id()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,9 +272,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A`
|
||||||
|
|
|
|
||||||
LL | struct A;
|
LL | struct A;
|
||||||
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
||||||
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd)]
|
LL | #[derive(PartialEq, PartialOrd)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0369]: binary operation `<=` cannot be applied to type `A`
|
error[E0369]: binary operation `<=` cannot be applied to type `A`
|
||||||
|
@ -290,9 +290,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A`
|
||||||
|
|
|
|
||||||
LL | struct A;
|
LL | struct A;
|
||||||
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
||||||
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd)]
|
LL | #[derive(PartialEq, PartialOrd)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0369]: binary operation `>` cannot be applied to type `A`
|
error[E0369]: binary operation `>` cannot be applied to type `A`
|
||||||
|
@ -308,9 +308,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A`
|
||||||
|
|
|
|
||||||
LL | struct A;
|
LL | struct A;
|
||||||
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
||||||
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd)]
|
LL | #[derive(PartialEq, PartialOrd)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0369]: binary operation `>=` cannot be applied to type `A`
|
error[E0369]: binary operation `>=` cannot be applied to type `A`
|
||||||
|
@ -326,9 +326,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A`
|
||||||
|
|
|
|
||||||
LL | struct A;
|
LL | struct A;
|
||||||
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
| ^^^^^^^^^ must implement `PartialOrd<_>`
|
||||||
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd)]
|
LL | #[derive(PartialEq, PartialOrd)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 15 previous errors
|
error: aborting due to 15 previous errors
|
||||||
|
|
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(Eq, Ord, PartialEq, PartialOrd)]`
|
||||||
|
|
|
||||||
|
LL | #[derive(Eq, Ord, PartialEq, 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(Eq, Ord, PartialEq, PartialOrd)]`
|
||||||
|
|
|
||||||
|
LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
|
@ -16,9 +16,9 @@ LL | let w = u.clone();
|
||||||
= note: the following trait bounds were not satisfied:
|
= note: the following trait bounds were not satisfied:
|
||||||
`CloneNoCopy: Copy`
|
`CloneNoCopy: Copy`
|
||||||
which is required by `U5<CloneNoCopy>: Clone`
|
which is required by `U5<CloneNoCopy>: Clone`
|
||||||
help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
|
help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(Copy)]
|
LL | #[derive(Clone, Copy)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `U1: Copy` is not satisfied
|
error[E0277]: the trait bound `U1: Copy` is not satisfied
|
||||||
|
|
|
@ -16,9 +16,9 @@ LL | let w = u.clone();
|
||||||
= note: the following trait bounds were not satisfied:
|
= note: the following trait bounds were not satisfied:
|
||||||
`CloneNoCopy: Copy`
|
`CloneNoCopy: Copy`
|
||||||
which is required by `U5<CloneNoCopy>: Clone`
|
which is required by `U5<CloneNoCopy>: Clone`
|
||||||
help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
|
help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]`
|
||||||
|
|
|
|
||||||
LL | #[derive(Copy)]
|
LL | #[derive(Clone, Copy)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `U1: Copy` is not satisfied
|
error[E0277]: the trait bound `U1: Copy` is not satisfied
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue