Now I want to state that every hunter is a runner. For it I write:
impl Runner for Hunter {} //compiler warns that dyn is for some reason required
Then I write some code like this:
struct Dog {}
impl Hunter for Dog {}
Dog{}.run
And I expect any dog to know how to run because it knows how to hunt, as was explicitly stated. But for some reason, compiler freaks out and emits error saying no method named runfound for structDoge in the current scope.
Am I doing it wrong or is it not possible at all? Also, why compiler wants to put dyn when you state equivalence for type classes? Would existential dyn Hunter and universal Dog types be equal, such that run() member would inhabit both or only the former one?
This means, “for every concrete type T that is a Hunter, implement the Runner trait for T.”
dyn Hunter is a trait object type. Dog and dyn Hunter are both types that implement the Hunter trait. However, they are distinct types, so implementing a trait for one of them does not implement it for the other.
In older versions of Rust, dyn Hunter was just spelled Hunter. That is, the trait and the type had the same name. This was confusing, so the dyn keyword was added. The old syntax is deprecated but hasn't been removed yet, which is why your original code compiled with a warning.
to declare that Hunter may only be implemented for a type that already implements Runner -- which formalizes "every hunter is a runner".
Whether this technique (making Hunter into an extension trait) or @mbrubeck's suggestion (writing a blanket impl for Runner) will work better for you depends on the details of your code. If you want to implement Runner using the methods on Hunter, use a blanket impl. If the behavior described by Runner needs to be implemented separately from the extra behavior described by Hunter, use an extension trait.