Looking for crate: custom derive PartialEq for floats


#1

For unit tests I need compare structs with f64/f32.
So I am looking for crate with such functionality:

#[derive(FloatPartialEq)]
struct Foo {
 #[FloatPartialEq(epsilon = "0.1")]
 x: f32,
 id: String,
 geo_code: [u8; 2],
}

Has anyone heard of such crate or crate with similar functionality?


#2

Note that an epsilon definition of PartialEq is actually illegal (though not UB). The trait requires that a == b && b == c --> a == c, and that’s trivially not true with epsilon – consider -0.07, 0, and 0.07 (with an epsilon of 0.1), for example.

You could consider OrderedFloat<f32> from https://crates.io/crates/ordered-float if you just want #[derive(PartialEq)] to work on your type.


#3

Yes, I know, but in my unit tests I obviosly don’t use transitive property.

Yes I want just that. But how this crate helps? I can not see how specify epsilon for OrderedFloat and I need several epsilons for f32 and f64, like:

struct Foo {
  lat: f64, //eps = (1_f64 / 60. / 60. / 100.).to_radians()
  h: f64, //eps = 0.5
}

#4

Other possibilities for unit tests include things like https://crates.io/crates/assert_approx_eq (From the thread Assert_eq! for float numbers)


#5

I already use this crate, look who is author of question that you linked.

The problem in automatization,
yes I can write, and at now I actually do it:

#[cfg(test)]
impl PartialEq for Foo {
}

but several time I added new data field to struct Foo, and
forget update imp PartialEq, so at now I am looking for derive/proc_macro that automate things for me.


#6

I think the problem is more reasoning about associated constants than return types, but yes.

The compiler currently seems unable to resolve even the most basic output/associated-type requirements:

trait SomeTrait {
    type Output;
    
    fn get() -> Self::Output;
}

struct X;
struct Y;

impl SomeTrait for X {
    type Output = i32;
    
    fn get() -> i32 { 42 }
}
impl SomeTrait for Y {
    type Output = bool;
    
    fn get() -> bool { true }
}

fn main() {
    let value: i32 = SomeTrait::get();
}

fails - https://play.rust-lang.org/?gist=d894b844286169224994eb28895629f1&version=stable

Worth noting that there is an upcoming change to the inference engine planned. Mainly, chalk is planning on being integrated into rustc. I’m not 100% sure that chalk will be able to solve problems like this either, but it might do that.