-
Notifications
You must be signed in to change notification settings - Fork 13k
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
very slow derived PartialEq/PartialOrd implementation of enum #31886
Comments
Expanded: enum Eu64 { Au64 = 0, Bu64 = 9223372036854775808, }
impl ::std::cmp::PartialOrd for Eu64 {
#[inline]
fn partial_cmp(&self, __arg_0: &Eu64)
-> ::std::option::Option<::std::cmp::Ordering> {
/* elided */
}
#[inline]
fn lt(&self, __arg_0: &Eu64) -> bool {
/* elided */
}
#[inline]
fn le(&self, __arg_0: &Eu64) -> bool {
/* elided */
}
#[inline]
fn gt(&self, __arg_0: &Eu64) -> bool {
{
let __self_vi =
unsafe { ::std::intrinsics::discriminant_value(&*self) } as
i32;
let __arg_1_vi =
unsafe { ::std::intrinsics::discriminant_value(&*__arg_0) } as
i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Eu64::Au64, &Eu64::Au64) => false,
(&Eu64::Bu64, &Eu64::Bu64) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { __self_vi.gt(&__arg_1_vi) }
}
}
#[inline]
fn ge(&self, __arg_0: &Eu64) -> bool {
/* elided */
}
}
impl ::std::cmp::PartialEq for Eu64 {
/* elided */
} Red flags:
Other than that, I don't see what's causing the slowdown. (edit: was wrong) The full expanded code exhibits the same behavior. With the cast to (edit again) It has to cast in case the repr is signed, because otherwise the comparison will be backwards. But I don't see how to get it right, because at deriving time there isn't enough information to infer the repr (might have to look up consts, etc). Maybe if we redesign the trait DiscriminantValue<T> {
type Discriminant: Eq + Ord;
fn value(&self) -> Self::Discriminant;
} |
In a debugger, it is always stuck on the line (of the expanded source): 80 (&Eu64::Bu64, &Eu64::Bu64) => false, Disassembly shows it stuck on this instruction: => 0x0000555555558b39 <+169>: jmp 0x555555558b39 <oli_exp::Eu64.::std::cmp::PartialOrd::gt+169> Well then... I don't know x86 assembly but that looks like an infinite loop to me! I dumped the assembly from rustc and found this gem: .LBB7_6:
.LBB7_7:
jmp .LBB7_6
|
Oh, suddenly it makes sense. |
Talked with @talchas on IRC. Turns out if you give a value for an enum variant, it has to be the same type as the given |
Obnoxiously
both compiles and prints "0 9223372036854775808" on 32-bit (same with So values that don't fit in an i32 give silently crazy behavior on 32-bit in other places. |
It was originally intended to be i32, but it isn't. Fixes rust-lang#31886.
It was originally intended to be i32, but it isn't. Fixes rust-lang#31886.
cleanups and fixes for #[derive] This contains a bunch of little cleanups and fixes to `#[derive]`. There are more extensive comments on each individual commit. - hygiene cleanups - use `discriminant_value` instead of variant index in `#[derive(Hash)]` - ~~don't move out of borrowed content in `#[derive(PartialOrd, PartialEq)]`~~ - use `intrinsics::unreachable()` instead of `unreachable!()` I don't believe there are any breaking changes in here, but I do want some more eyes on that. Fixes rust-lang#2810 (!), I believe (we still assume that "std" or "core" is the standard library but so does the rest of rustc...). Fixes rust-lang#21714 (cc @apasel422). ~~Fixes~~ (postponed) rust-lang#24047 (cc @withoutboats @bluss). Fixes rust-lang#31714 (cc @alexcrichton @bluss). Fixes rust-lang#31886 (cc @oli-obk).
It was originally intended to be i32, but it isn't. Fixes rust-lang#31886.
cleanups and fixes for #[derive] This contains a bunch of little cleanups and fixes to `#[derive]`. There are more extensive comments on each individual commit. - hygiene cleanups - use `discriminant_value` instead of variant index in `#[derive(Hash)]` - ~~don't move out of borrowed content in `#[derive(PartialOrd, PartialEq)]`~~ - use `intrinsics::unreachable()` instead of `unreachable!()` I don't believe there are any breaking changes in here, but I do want some more eyes on that. Fixes #2810 (!), I believe (we still assume that "std" or "core" is the standard library but so does the rest of rustc...). Fixes #21714 (cc @apasel422). ~~Fixes~~ (postponed) #24047 (cc @withoutboats @bluss). Fixes #31714 (cc @alexcrichton @bluss). Fixes #31886 (cc @oli-obk).
It was originally intended to be i32, but it isn't. Fixes rust-lang#31886.
derive: assume enum repr defaults to isize derive: assume enum repr defaults to isize Fixes #31886. Spawned from #32139. r? @alexcrichton
The following code goes into an infinite loop or at least takes more than 10 seconds without optimizations. With optimizations it runs and the assertion fails. If anything but
0
and0x8000_0000_0000_0000
are chosen for the discriminants, the code finishes instantly even in debug mode. PlaygroundThere's something odd going on anyway, as the discriminant is inferred to be
isize
instead ofu64
(This unit test seems to suggest it should beu64
)cc #24290 @pnkfelix
The text was updated successfully, but these errors were encountered: