Quantcast
Viewing latest article 38
Browse Latest Browse All 44

How can I create hashable trait objects / trait objects with generic method parameters?

I have some structs that implement both Hash and MyTrait. I'm using them as &dyn MyTrait trait objects.

Now I want &dyn MyTrait to also implement Hash. I've tried a few things:

  • Naively, trait MyTrait: Hash {}:

    the trait `MyTrait` cannot be made into an object
  • Then I tried this:

    impl Hash for dyn MyTrait {    fn hash<H: Hasher>(&self, hasher: &mut H) {        // ...    }}

    but I need to delegate to the hash method of the concrete type of self, I think.

  • So the naive next step is to put this on MyTrait:

    fn my_hash<H: Hasher>(&self, hasher: &mut H);

    which brings me right back to the first point.

  • I read something about using a trait object instead of generic parameter, which sounds smart, so I put this on MyTrait

    fn my_hash(&self, hasher: &mut H);

    Then I need to actually implement this. Preferably not by hand for every trait:

    impl<T: 'static + Hash> MyTrait for T {    fn as_any(&self) -> &dyn Any {        self as &dyn Any    }    fn my_hash(&self, hasher: &mut Hasher) {        self.as_any().downcast_ref::<T>().unwrap().hash(hasher)    }}

    but then

    the trait bound `std::hash::Hasher: std::marker::Sized` is not satisfied`std::hash::Hasher` does not have a constant size known at compile-time

    So I'd have to downcast Hasher

  • If downcasting Hasher is the way, I need a generic parameter H that can convert to an AnyHasher, Let's try:

    trait AnyHasher {    fn as_any(&self) -> &dyn Any;}impl<H: 'static + Hasher> AnyHasher for H {    fn as_any(&self) -> &dyn Any {        self as &dyn Any    }}

    and then to downcast

    impl<T: 'static + Hash, H: 'static + Hasher> MyTrait for T {    // ...    fn my_hash(&self, hasher: &mut AnyHasher) {        let h = hasher.as_any().downcast_ref::<H>().unwrap();        self.as_any().downcast_ref::<T>().unwrap().hash(h)    }}

    but alas

    the type parameter `H` is not constrained by the impl trait, self type, or predicates

    which I guess is true, but then I'm stuck. (Also it seems kind of ridiculous so far).

Can this can be done? If so, how?

I previously asked about PartialEq for trait objects, which was hard because information the concrete type of the trait object is needed. That was solved with downcasting, but I didn't manage to apply that solution here.


Viewing latest article 38
Browse Latest Browse All 44

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>