Reputation: 121
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
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