How can I avoid dynamic dispatch?

In order to move handle_state into a trait my refactoring attempt of the code

struct State;
impl State {
    #[allow(dead_code)]
    fn handle_state(&self) {}
}

trait StateView: Sized {
    fn view(_: State) -> Vec<Self>;
}

struct ViewImpl;
impl StateView for ViewImpl {
    fn view(s: State) -> Vec<Self> {
        s.handle_state();
        vec![Self]
    }
}

struct Context<V: StateView> {
    view: Vec<V>,
}

ended in

trait StateTrait {
    fn handle_state(&self);
}

struct State;
impl StateTrait for State {
    fn handle_state(&self) {}
}

trait StateView: Sized {
    fn view(_: &dyn StateTrait) -> Vec<Self>;
}

struct ViewImpl;
impl StateView for ViewImpl {
    fn view(s: &dyn StateTrait) -> Vec<Self> {
        s.handle_state();
        vec![Self]
    }
}

struct Context<V: StateView> {
    view: Vec<V>,
}

Would it be possible to avoid usage of dynamic dispatch in the refactored code?
Something like

...
trait StateView: Sized {
    fn view(_: &StateTrait) -> Vec<Self>;
}

Use a generic parameter:

 trait StateView: Sized {
-    fn view(_: &dyn StateTrait) -> Vec<Self>;
+    fn view<S: StateTrait>(_: &S) -> Vec<Self>;
 }
1 Like

Why the compiler suggests add `dyn` keyword before this trait instead of generic parameter for?

 trait StateView: Sized {
-    fn view(_: &dyn StateTrait) -> Vec<Self>;
+    fn view(_: &StateTrait) -> Vec<Self>;
 }

There's history. Back in Rust 2015 edition, you didn't need the dyn keyword to request dynamic dispatch on a trait object; you just wrote fn view(_: &StateTrait), and the compiler "knew" that you meant what we now write as fn view(_: &dyn StateTrait).

I suspect the suggestion hasn't been updated since the days when adding dyn was almost certainly the right thing to do, and I'd file a diagnostic issue explaining what you'd expect the compiler to offer as help (something like "for dynamic dispatch, add dyn, for static dispatch use a generic parameter")

4 Likes

I agree that adding dyn should not be the only hint.

2 Likes

created a ticket suggestion to use generic parameter in case of "error[E0782]: trait objects must include the `dyn` keyword" · Issue #125139 · rust-lang/rust · GitHub

1 Like