Skip to content
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

#[derive]'d PartialOrd and Ord use variant declaration order, not explicit discriminant values, for (partially) C-like enums #15523

Closed
huonw opened this issue Jul 8, 2014 · 8 comments · Fixed by #24270
Assignees
Labels
A-syntaxext Area: Syntax extensions E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Milestone

Comments

@huonw
Copy link
Member

huonw commented Jul 8, 2014

#[deriving(Ord, PartialOrd, Eq, PartialEq, Show)]
enum Foo {
    A = 10,
    B = 0,
    C,
}

fn main() {
    let v = [A, B, C];

    println!("      deriving\tdiscriminant");
    for x in v.iter() {
        for y in v.iter() {
            println!("{}, {}: {}  \t{}", *x, *y, x.cmp(y), (*x as uint).cmp(&(*y as uint)));
        }
    }
}
      deriving  discriminant
A, A: Equal     Equal
A, B: Less      Greater
A, C: Less      Greater
B, A: Greater   Less
B, B: Equal     Equal
B, C: Less      Less
C, A: Greater   Less
C, B: Greater   Greater
C, C: Equal     Equal

That is, deriving considers A the smallest, but it has the largest discriminant.

I would think that #[deriving] should be changed to use the explicit discriminants (if they are available), but there is some possibility that declaration order may be the correct thing (you can always reorder the variants to match their discriminants).

There's also an edge case due to the (apparent?) untypedness of enum variant discriminants: when ordering enum Foo { A = 1, B = -1 }, is the discriminant of B considered negative, or is it positive and huge?

@huonw
Copy link
Member Author

huonw commented Jul 8, 2014

nominating (for BC-libs, although #[deriving] is on the border between the libraries and language): if we do change this behaviour it would be a breaking change.

@pnkfelix
Copy link
Member

Assigning 1.0, P-backcompat-libs.

(I want to write down what the actual ordering that we want for "partial c-like enums" somewhere, as part of solving this.)

@pnkfelix pnkfelix added this to the 1.0 milestone Jul 10, 2014
@pnkfelix
Copy link
Member

spawned off of PR #15503

@aturon
Copy link
Member

aturon commented Jan 8, 2015

Re-nominating. Is this still an issue we want to tackle? If so, it probably belongs on beta.

@nrc nrc changed the title #[deriving]'d PartialOrd and Ord use variant declaration order, not explicit discriminant values, for (partially) C-like enums #[derive]'d PartialOrd and Ord use variant declaration order, not explicit discriminant values, for (partially) C-like enums Jan 8, 2015
@pnkfelix
Copy link
Member

pnkfelix commented Jan 8, 2015

leaving on the 1.0 milestone, mostly because if we don't actually get around to doing this, it won't be the end of the world (at least, that's IMO)

@brson brson added E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Jan 8, 2015
@brson
Copy link
Contributor

brson commented Jan 8, 2015

@huonw will mentor

@pnkfelix
Copy link
Member

see also #15620 (which strikes me as a logical subtask of this)

@pnkfelix
Copy link
Member

pnkfelix commented Apr 2, 2015

If we're going to fix this, it needs to be for 1.0.

It seems ilke it would be better to just use the discriminant value.

bors added a commit that referenced this issue Apr 10, 2015
Use `discriminant_value` intrinsic for `derive(PartialOrd)`

[breaking-change]

This is a [breaking-change] because it can change the result of comparison operators when enum discriminants have been explicitly assigned.  Notably in a case like:
```rust
#[derive(PartialOrd)]
enum E { A = 2, B = 1}
```

Under the old deriving, `A < B` held, because `A` came before `B` in the order of declaration.  But now we use the ordering according to the provided values, and thus `A > B`.  (However, this change is very unlikely to break much, if any, code, since the orderings themselves should all remain well-defined, total, etc.)

Fix #15523
bors added a commit that referenced this issue Apr 10, 2015
Use `discriminant_value` intrinsic for `derive(PartialOrd)`

[breaking-change]

This is a [breaking-change] because it can change the result of comparison operators when enum discriminants have been explicitly assigned.  Notably in a case like:
```rust
#[derive(PartialOrd)]
enum E { A = 2, B = 1}
```

Under the old deriving, `A < B` held, because `A` came before `B` in the order of declaration.  But now we use the ordering according to the provided values, and thus `A > B`.  (However, this change is very unlikely to break much, if any, code, since the orderings themselves should all remain well-defined, total, etc.)

Fix #15523
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-syntaxext Area: Syntax extensions E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants