Enum with Box<trait> and comparsion


#1

I have enum with Box and I want compare the enum

use std::fmt::Debug;

pub trait THeader : Debug + PartialEq {
    fn m(&self) {
        println!("hello");
    }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct THeader1;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct THeader2;

impl THeader for THeader1{}
impl THeader for THeader2{}
 
#[derive(Debug, PartialEq)]
pub enum Header {
    H(Box<THeader>),
}

fn main()
{
    let h1 = Header::H(Box::new(THeader1{}));
    let h2 = Header::H(Box::new(THeader2{}));
    if h1 == h2 {
        println!("eq");
    }
}

Playground

With this code I get error “the trait THeader cannot be made into an object, the trait cannot use Self as a type parameter in the supertraits or where-clauses”
Explain please what’s wrong here


#2

PartialEq has Self as a parameter to the equality functions. This violates object safety.

You’ll need to implement PartialEq for Header manually, and define the semantics of object comparison: playground with a stub impl


#3

I have a similar problem and I can’t figure out how to do the object comparison. I can’t just do self == other right? I thought of implementing something like PartialEq (Rhs: Self…) but I got the “Self” problem.

Here’s a similar example without an enum.


#4

You need to decide how you’d like to compare arbitrary THeader values. For example, THeader can define some method(s) that returns some data that will be used for comparison.


#5

Thanks. I guessing THeader can’t define a method returning a trait so I’m under the impression that I’m losing the advantage of using a trait. I can’t use any object and only implement THeader and call it a day. I’m guessing the method that will return the data used for comparaison will need to have knowledge about every implementers.


#6

Well, forgetting the mechanics for a second - how would you compare two arbitrary THeader types? You’ll need to somehow unify across all possible THeader impls so they can be compared. Or are you saying that’s not fundamentally possible in your case?


#7

You can have a method on THeader which returns something else that is comparable, such as a &str. Then instead of your trait extending PartialEq, you just call it from Header's implementation. Example: https://play.rust-lang.org/?gist=156191dd865d80b2daa510822cfef27c&version=stable&mode=debug&edition=2015