-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fully generalize cmp instances #20063
Comments
I don't think we need to do this prior to stabilization, since we can always safely generalize in the future. I'd also like to put some thought into how general we want to make things, but the example above seems like a good minimum. |
A bit of follow up: I'm seeing some cases where e.g. the |
This patch marks `PartialEq`, `Eq`, `PartialOrd`, and `Ord` as `#[stable]`, as well as the majorify of manual implementaitons of these traits. The traits match the [reform RFC](rust-lang/rfcs#439). In the future, many of the impls should be generalized; see rust-lang#20063. However, there is no problem stabilizing the less general impls, since generalizing later is not a breaking change. r? @alexcrichton
What's the status of this with #20065 merged? |
I am guessing the status is that it's done, so I'm giving it a close. Let me know if there's anything specific still missing. |
@steveklabnik No, this hasn't been done yet. Basically it would require a sweep through all existing impls to generalize them. I'm not sure where you want to track tickets like this. It's generally backwards compatible to make these changes, and not exactly high priority, but something nice for expressiveness and consistency (and definitely does not require an RFC). |
Yeah, it's hard because it's not directly actionable, it's more like 'double check all these things.' It'd be nice if we had an actual list. |
I think the following command gives you a "Good Enough" list of implementations of
Example output on liballoc:
After running that command on every crate, and filtering out types that only have lifetime parameters like
I'll let @aturon pick the subset that would be nice to have for 1.0 ( Disclaimer: This list is not exhaustive, because some lines got wrapped around by the pretty printer and the grep expression expects a single line match. |
@japaric Sorry for the delay, this comment was buried in my inbox (and I was away on vacation). Anyway:
That makes good sense to me as a 1.0 starting point, and I certainly agree that not all of the listed types should get this treatment. |
cc #20927 |
I took a shot at just implementing this manually for
I feel like there should be a nicer solution here. I'm pretty sure that adding type annotations to every |
Argh! Sounds like it may not be possible to generalise. :( |
It seems type parameter defaults may help to solve the issue @shepmaster met: #![feature(default_type_parameter_fallback)]
enum Maybe<T> { Nothing, Just(T) }
use Maybe::*;
impl<T, U = T> PartialEq<Maybe<U>> for Maybe<T>
where T: PartialEq<U>
{
fn eq(&self, other: &Maybe<U>) -> bool {
match (self, other) {
(&Nothing, &Nothing) => true,
(&Just(ref a), &Just(ref b)) => a == b,
_ => false,
}
}
}
fn main() {
println!("{}", Nothing == Just("foo"));
println!("{}", Just("foo") == Nothing);
} Without the default, both |
How frustrating (and interesting!). Is it possible to improve default type parameters to allow mutual identity defaults? |
You aren't currently allowed to forward declare defaults, we might be able to lift that requirement having both be equal should just give you this set of equalities:
|
I'm up late working on a paper and this thought came to mind, you can encode a cute little trait trick in order to apply a secondary default: #![feature(default_type_parameter_fallback)]
enum Maybe<T> { Nothing, Just(T) }
use Maybe::*;
trait DefaultTo<Ty, Default> {}
impl<T, U=T> DefaultTo<U, T> for () {}
impl<U, T = U> PartialEq<Maybe<U>> for Maybe<T>
where T: PartialEq<U>,
(): DefaultTo<U, T>
{
fn eq(&self, other: &Maybe<U>) -> bool {
match (self, other) {
(&Nothing, &Nothing) => true,
(&Just(ref a), &Just(ref b)) => a == b,
_ => false,
}
}
}
fn main() {
println!("{}", PartialEq::eq(&Nothing, &Just("foo")));
println!("{}", PartialEq::eq(&Just("foo"), &Nothing));
} |
@rust-lang/lang How realistic would it be to for a solution for the problem here to be designed and accepted any time soon? Ideally we'd make |
Note that it wouldn't need to have |
Some languages are able to do point-to-point vectorial comparisons:
Such overloading would be possible, for example, if trait
In whatever case, is there an RFC aimed at enabling point-to-point vector comparisons (or even more general comparisons such as functional point-to-point comparisons, etc.)? |
With cmp/ops reform, all of the comparison traits allow the types of the two sides to differ. However, the traits provide a default type for the right-hand size that is the same as the left-hand side. Thus, an impl like:
is more limited than it needs to be; it could instead be
(Of course, you could imagine being even more general than that, allowing Rc values to be compared to other values.)
The various impls in the standard library should probably be generalized along these lines; currently a few are but most aren't.
The text was updated successfully, but these errors were encountered: