Atsuki Takahashi
Atsuki Takahashi

Reputation: 121

Can Rust call abstract functions?

I found some complicated code in the websocket library which seems to call an abstract function in the Receiver trait.

fn recv_message<'m, D, M, I>(&mut self) -> WebSocketResult<M>
    where M: Message<'m, D, DataFrameIterator = I>,
          I: Iterator<Item = D>,
          D: DataFrame
{
    let dataframes = try!(self.recv_message_dataframes());
    Message::from_dataframes(dataframes) // Isn't this an abstract function?
}

The code for ws::Message trait:

pub trait Message<'a, F>: Sized
    where F: DataFrame
{
    type DataFrameIterator: Iterator<Item = F>;
    fn from_dataframes<D>(frames: Vec<D>) -> WebSocketResult<Self> where D: DataFrame;
    fn dataframes(&'a self) -> Self::DataFrameIterator;
}

It looks like it shouldn't work because Rust wouldn't know which function to call. How does it work?

Upvotes: 1

Views: 473

Answers (1)

DK.
DK.

Reputation: 59105

The key is the signature of the method:

fn from_dataframes<D>(frames: Vec<D>) -> WebSocketResult<Self>

When the compiler goes to unify the types, it can use the return type of recv_message (i.e. WebSocketResult<M>) to infer that the result of from_dataframes must be the same type, which means the Self type in question is M, which means that what you really meant was:

<M as Message>::from_dataframes(dataframes)

If there was no connection between the implementing type and the method signature, then it wouldn't work, because the compiler would have nothing to base its reasoning on.

Upvotes: 3

Related Questions