Trait bounds on trait objects

I'm trying to implement a trait on a structure containing a reference to a trait object. By bounding the trait object like below. Is there some way to achieve this?

trait Foo<T> {
    fn foo(&self, t: T) -> u32;
}

trait Bar {
    fn bar(self, n: u32) -> Self;
}

struct DoesFoo {
    value: u32
}

struct Wrapper<'a, T> {
    wrapped: &'a dyn Foo<T>,
}

impl Foo<u32> for DoesFoo {
    fn foo(&self, t: u32) -> u32 {
        self.value + t
    }
} 

impl<'a, T> Bar for Wrapper<'a, T> 
where T: Bar,
{
    fn bar(self, n: u32) -> Self {
        self.wrapped.bar(n)
    }
}

fn main() {
}


(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `bar` found for reference `&'a (dyn Foo<T> + 'a)` in the current scope
  --> src/main.rs:27:22
   |
27 |         self.wrapped.bar(n)
   |                      ^^^ method not found in `&'a (dyn Foo<T> + 'a)`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
note: `Bar` defines an item `bar`, perhaps you need to implement it
  --> src/main.rs:5:1
   |
5  | trait Bar {
   | ^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

It isn't clear what you want to achieve here. What is the expected behaviour if self.wrapped does not implement Bar? Nothing as written guarantees something that implements Foo will also implement Bar. If you want anything that implements Foo to also implement Bar then you need to add that to the definition of Foo:

trait Foo<T> : Bar {
    fn foo(&self, t: T) -> u32;
}

Otherwise, I may need some more information on what you are trying to do.

EDIT: Of course, bar() takes ownership of self, so just making something that implements Foo also implement Bar is not enough when you have a reference. What are you expecting the call to self.wrapped.bar() to do?

T implements Bar, so I'm justing trying to call T's implementation. Basically I want to say that the T in &'a dyn Foo<T> implemetns bar and call it.

These traits are simplified versions of NoiseFn and Seedable from the noise-rs crate. And I'm trying to implement Seedable for Abs: https://docs.rs/noise/0.7.0/noise/struct.Abs.html

There is no guarantee in general that something that implements Foo<T> actually contains a T. If you want to be able to extract T, then you need a method on Foo saying that is possible.

2 Likes

Ah, I think I get now. Thanks

1 Like