-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Treat wasmtime::component::Val::Float{32,64}
NaNs as equal
#5535
Treat wasmtime::component::Val::Float{32,64}
NaNs as equal
#5535
Conversation
As requested by @alexcrichton in #5510 (comment) |
b96bd8e
to
c6adbad
Compare
wasmtime::component::Val::Float{32,64}
NaNs is equalwasmtime::component::Val::Float{32,64}
NaNs as equal
Subscribe to Label Actioncc @peterhuene
This issue or pull request has been labeled: "wasmtime:api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
When we had a similar concern in Cranelift we ended up introducing a separate function that can just special-case floats and use a derived implementation of Although you don't want bitwise equality here, the same pattern should work. It avoids the need to list every enum variant, and the possibility of bugs when new variants are added. Another way to avoid bugs is to have two cases for each variant, like the implementation of PartialEq for DataValue. But I think here it's fine to use |
That certainly could work, but it is significantly more code because of the component model's composite and parameterized types. |
Huh, I don't see why. I'm suggesting putting back the impl Val {
pub fn funny_eq(&self, other: &Val) -> bool {
match (self, other) {
// This breaks conformance with IEEE-754 equality to simplify testing logic.
(Self::Float32(l), Self::Float32(r)) => l == r || (l.is_nan() && r.is_nan()),
(Self::Float64(l), Self::Float64(r)) => l == r || (l.is_nan() && r.is_nan()),
_ => self == other,
}
}
} Or, if it's only intended to be used in one place, just put this match there. |
I saw why immediately after I posted that comment. I forgot the derived implementations wouldn't be calling this. I take it all back! So this PR seems about as good as it can be, except I'd still propose the second pattern I mentioned to ensure that the compiler will catch the error if new variants are added to |
In bytecodealliance#5510 we changed the value types of these variants from u{32,64} to f{32,64}. One side effect of this change was that two NaN values would no longer compare equal. While this is behavior complies with IEEE-754 floating point operations, it broke equality assumptions in fuzzing. This commit changes equality for Val to make NaNs compare equal. Since the component model requires NaN canonicalization, all NaN bit representations compare equal, which is different from the original behavior. This also gives Vals the semantics of Eq again, so that trait impl has been reintroduced to related types as well.
c6adbad
to
31ee10c
Compare
Done. |
I don't have full context here, but I wanted to make sure it's considered that floating-point equality considers |
I think the issue is just NaN inequality, but I don't entirely understand the fuzzing code in question. |
I'm going to go ahead and merge this since it fixes the fuzz issues that have cropped up, but I think it'd be reasonable to have a follow-up for +/- 0 handling as well. |
… as inequal Following up on bytecodealliance#5535, treat positive and negative zero as inequal in wasmtime::component::Val::Float{32,64}'s `PartialEq` logic. IEEE 754 equality considers these values equal, but they are semantically distinct values, and testing and fuzzing should be aware of the difference.
… as inequal (#5562) Following up on #5535, treat positive and negative zero as inequal in wasmtime::component::Val::Float{32,64}'s `PartialEq` logic. IEEE 754 equality considers these values equal, but they are semantically distinct values, and testing and fuzzing should be aware of the difference.
In #5510 we changed the value types of these variants from u{32,64} to f{32,64}. One side effect of this change was that two NaN values would no longer compare equal. While this is behavior complies with IEEE-754 floating point operations, it broke equality assumptions in fuzzing.
This commit changes equality for Val to make NaNs compare equal. Since the component model requires NaN canonicalization, all NaN bit representations compare equal, which is different from the original behavior.
This also gives Vals the semantics of Eq again, so that trait impl has been reintroduced to related types as well.