2

I'm trying to implement a set of traits in a way that allows me to test equality between types. I followed How to test for equality between trait objects?. I can use the tr_eq method to test between types, but I can't get the == operator to work. What am I doing wrong here?

use std::any::Any;
use std::fmt::Debug;

pub trait Obj<'a>: Debug + Any {
    fn as_any(&self) -> &Any;

    fn tr_eq(&self, other: &Obj) -> bool;
}

impl<'a> Obj<'a> for bool {
    fn as_any(&self) -> &Any {
        self
    }

    fn tr_eq(&self, other: &Obj) -> bool {
        other
            .as_any()
            .downcast_ref::<bool>()
            .map_or(false, |a| self == a)
    }
}

impl<'a> PartialEq for Obj<'a> {
    fn eq(&self, other: &Obj) -> bool {
        self.tr_eq(other)
    }
}

#[derive(Debug, PartialEq)]
pub struct Marker;

impl<'a> Obj<'a> for Marker {
    fn as_any(&self) -> &Any {
        self
    }

    fn tr_eq(&self, other: &Obj) -> bool {
        other
            .as_any()
            .downcast_ref::<Marker>()
            .map_or(false, |a| self == a)
    }
}

fn main() {
    println!("true == Marker: {:?}", true == Marker {}); // error
    println!("true == true: {:?}", true == true);
    println!(
        "&true as &Obj == &Marker as &Obj: {:?}",
        &true as &Obj == &Marker {} as &Obj
    );
    println!("Marker.tr_eq(&true): {:?}", Marker {}.tr_eq(&true));
    println!(
        "&Marker as &Obj == (&true as &Obj): {:?}",
        &Marker {} as &Obj == (&true as &Obj)
    );
    println!("false.tr_eq(&true): {:?}", false.tr_eq(&true));
    println!("true.tr_eq(&true): {:?}", true.tr_eq(&true));
    println!("Marker==Marker: {:?}", Marker {} == Marker {})
}
error[E0308]: mismatched types
  --> src/main.rs:47:46
   |
47 |     println!("true == Marker: {:?}", true == Marker {});
   |                                              ^^^^^^^^^ expected bool, found struct `Marker`
   |
   = note: expected type `bool`
              found type `Marker`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
candronikos
  • 159
  • 1
  • 13
  • 1
    Possible duplicate of [How to test for equality between trait objects?](https://stackoverflow.com/questions/25339603/how-to-test-for-equality-between-trait-objects) – E_net4 May 30 '18 at 23:12
  • 1
    You're not doing anything wrong; it's not possible to implement `PartialEq` such that `true == Marker {}` will compile, because [you can't implement `PartialEq` for `bool`](https://stackoverflow.com/questions/25413201/how-do-i-implement-a-trait-i-dont-own-for-a-type-i-dont-own). (You *can* implement `PartialEq` for `Marker`, which would make the reverse (i.e. `Marker {} == true`) work. But it's probably better just to stick to trait objects and keep them behind `&` or `Box`.) – trent May 31 '18 at 02:16
  • Hi @trentcl, What if I wrap `bool` in a `struct Bool(bool)`? I'm getting other errors but I want to check if I'm on the right track. Also interested in implementing `PartialEq` for Marker but I don't fully understand. Can you elaborate? – candronikos May 31 '18 at 04:48
  • 1
    Sorry, I was wrong about that; `impl PartialEq for bool` works. What you can't do is `impl<'a, T: Obj<'a>> PartialEq for bool`, and you *definitely* can't `impl<'a, T: Obj<'a>, U: Obj<'a>> PartialEq for T` (that's what you'd need to make any `==` comparison work between types that implement `Obj`). – trent May 31 '18 at 12:50

0 Answers0