-
-
Notifications
You must be signed in to change notification settings - Fork 122
Description
Description
The Ord
and PartialEq
implementations of minijinja::Value
work as follows:
- Coerce the types of the two
Value
s to be equal- Equal types are left as-is
- When both sides are integers, everything is converted to
i128
- When either side is a float, both sides are coerced to a float,
- Otherwise try to coerce to
i128
on both sides
- If this coercion was successful, do the comparison on the resulting values
- Otherwise, try to compare the values as if they were objects
This violates the transitivity property of the comparison traits, which, in addition to producing unexpected but niche behaviour, also can cause panics while sorting due to the new sorting algorithms of Rust 1.81 panicking on invalid Ord
implementations.
Reproduction steps
I wrote a small program that demonstrates the issue
use minijinja::Value;
fn main() {
let a = Value::from(i64::MAX as i128);
let b = Value::from(i64::MAX as f64);
let c = Value::from(i64::MAX as i128 + 1);
assert_eq!(a, b, "Equal because they are the same value");
assert_eq!(b, c, "Equal because the float approximations are equal");
assert_ne!(a, c, "Not equal because they are different values");
}
Additional helpful information:
- Version of minijinja: 2.2.0
- Version of rustc: 1.81.0
- Operating system and version: Ubuntu 22.04
Though none of the above should matter, I think this bug applies to all versions.
What did you expect
Equality and comparison operators should maintain their transitive properties. This is a hard problem with many corner cases. It would involve checking:
- if the float is an integer, otherwise the comparison should be false
- if the float is within the relevant integer range, otherwise the comparison should be false
- and then the comparison should happen in integers, not floats
This is much more complicated than the existing solution, so it's understandable you went this route, but it does have the issue described above.
Also the above fix only works for (Partial)Eq
, fixing Ord
is much more complicated.