Skip to content

Make #[derive(Copy, Eq, Ord)] imply #[derive(Clone, PartialEq, PartialOrd)] #23905

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

Closed
wants to merge 9 commits into from

Conversation

erickt
Copy link
Contributor

@erickt erickt commented Mar 31, 2015

This reduces the amount of boilerplate users need to do in order to derive some common traits.

This is related to #23860.

cc @nikomatsakis, @aturon

@rust-highfive
Copy link
Contributor

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
trait_def.expand(cx, mitem, item, push);

partial_ord::expand_deriving_partial_ord(cx, span, mitem, item, push)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The derived partial_cmp can be optimized in this case to just Some(self.cmp(other)).

EDIT: Hmm, though they're not totally equivalent in the presence of type paramters unfortunately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've got a build running that applies this PartialOrd optimization to non-generic types. I'll push it up when it finishes running.

@aturon
Copy link
Member

aturon commented Mar 31, 2015

🎯

@alexcrichton
Copy link
Member

Out of curiosity, is it still possible to have #[derive(Ord)] but a manual implementation of PartialOrd?

@sfackler
Copy link
Member

@alexcrichton I think the more common thing would be the opposite since PartialOrd has a trivial impl if you've already implemented Ord::cmp.

@alexcrichton
Copy link
Member

Hm true. In general I've been very worried in the past about this form of deriving as it seems like a footgun for various forms of configuration of deriving. For example it looks like instances of derive(Eq) with a manual PartialEq impl were removed in favor of a manual Eq impl. I worry about the "half-derive" case, but it may not be too large of a worry in practice. For example adding an impl of Eq is just a marker trait so it's not so bad, and I'm not sure how much this applies to Ord and PartialOrd...

@erickt
Copy link
Contributor Author

erickt commented Apr 1, 2015

@alexcrichton: with this PR we could no longer provide a manual implementation of PartialOrd with #[derive(Ord)]. Is there ever a case where we'd want a manual implementation if we already have version of Ord? That also seems like it could be a source of bugs if the two were inconsistent.

@nikomatsakis
Copy link
Contributor

My main concern is whether this PR requires an RFC. It seems to be at least mildly controversial. Obviously this would have to land by 1.0 though! (I personally acknowledge @alexcrichton's concerns, but think that this PR is a net improvement on the current situation.)

@erickt
Copy link
Contributor Author

erickt commented Apr 1, 2015

@sfackler: I just pushed up a patch that simplifies generating PartialOrd for non-generic Ord types. I'm not sure if my metrics are right, but this PR appears to be shaving off about 100KB from libstd.dylib when compared with the latest nightly libstd.dylib, but I can't say if that's all due to this PR or some other optimizations going on. I could do a fresh build to compare the too if we want a real number.

@nikomatsakis
Copy link
Contributor

r+ from me (modulo RFC) but I'm not really that familiar with this code. Certainly I'd like to hear @sfackler or @huonw weigh in.

@bors
Copy link
Collaborator

bors commented Apr 2, 2015

☔ The latest upstream changes (presumably #23963) made this pull request unmergeable. Please resolve the merge conflicts.

@erickt
Copy link
Contributor Author

erickt commented Apr 2, 2015

I rebased on top of HEAD to avoid some merge conflicts and squashed some of the cleanup commits together.

erickt added 8 commits April 2, 2015 16:05
This allows #[derive(...)]` to create more than one impl
This PR generates a simplified `PartialOrd` implementation when the
type is `Ord` and non-generic. It produces essentially:

impl ::std::cmp::PartialOrd for $ty {
    fn partial_cmp(&self, other: &$ty) -> Option<std::cmp::Ordering> {
        Some(::std::cmp::Ord::cmp(self, other))
    }
}
@huonw
Copy link
Member

huonw commented Apr 3, 2015

Copying this comment to ensure it doesn't get lost: I believe it one should be able to make the simple-impls work via the self_args fields of Substructure.

Also, another minor point: what about supporting #[derive(Copy, Clone)] struct Foo; (i.e. explicitly write the Clone?)?

Alsoalso, I wonder about the case of optimising PartialOrd (e.g. maybe < can be computed faster than a full comparison). There's a big cliff between:

#[derive(Ord)]
struct Foo { ... }

and

struct Foo { ... }

impl Ord for Foo {
    fn cmp(&self, other: &Foo) -> Ordering {
        // ... lots of stuff ...
    }
}
impl PartialOrd for Foo {
     fn partial_cmp(&self, other: &Foo) -> Option<Ordering> { Some(self.cmp(other)) }
     fn lt(&self, other: &Foo) -> bool { /* supafast */ }
}

That said, it seems like this PR is the right default, and we can add an opt-out mechanism in future.

@nikomatsakis
Copy link
Contributor

Also, another minor point: what about supporting #[derive(Copy, Clone)] struct Foo; (i.e. explicitly write the Clone?)?

I thought the PR did permit this, albeit with a FIXME attached? (I tend to think we should just allow it and, at most, lint for it)

@erickt
Copy link
Contributor Author

erickt commented Apr 3, 2015

@nikomatsakis: Yes, this PR explicitly handles #[derive(Copy, Clone)]. A lint sounds fine to me.

bors added a commit that referenced this pull request Apr 6, 2015
This extracts some of the minor cleanup patches from #23905.
@huonw
Copy link
Member

huonw commented Apr 6, 2015

Oh, I wasn't clear: my reading of the PR was that the support for that was only for staging reasons. In any case, a lint (or nothing) sounds good to me.

@dcrewi
Copy link
Contributor

dcrewi commented Apr 13, 2015

This should probably be closed now, as the RFC has been resolved?

@alexcrichton
Copy link
Member

Yes thanks for the reminder @dcrewi! Closing for the same reasons as listed in the RFC.

bors added a commit that referenced this pull request Apr 18, 2015
This extracts some of the minor cleanup patches from #23905.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants