I've got a trait which looks like this:
pub trait ViewFactory {
type View: View;
fn create(&self) -> Self::View;
}
However, what I really want is this:
pub trait ViewFactory {
fn create(&self) -> impl View;
}
The reason I want this is because create()
typically returns an expression with a very complicated type signature such as Fragment<(Cond<String, String>, Element, Element, String, ForEach<Item, String>)>
and so on. It's very unergonomic to force everyone who wants to implement ViewFactory
to have to figure out the exact type that is produced by the expression.
Unfortunately, in order to cache the result from ViewFactory
I also need to know the return type. Here's a typical example of how a ViewFactory
gets used:
impl<Factory: ViewFactory> FactoryOutput for Factory {
type State = (Factory::View, <Factory::View as View>::State);
fn build(&self, cx: &mut Cx) -> Self::State {
let view = self.create(cx);
let state = view.build(cx);
(view, state)
}
fn rebuild(&self, cx: &mut Cx, &mut state: Self::State) {
state.0 = self.create(cx);
let state = view.rebuild(cx, &state.1);
}
}
In other words, the associated type needs to know the exact type returned by create()
so that it can create a tuple containing the output of create()
.
If create
was a plain function instead of a trait method, I might be able to infer the return type using some fancy generics. But there doesn't seem to be a way to do this with a method.
Type erasing the result of create()
is problematic because I'd need to box the result, which means an additional memory allocation. The call to create()
is meant to be cheap, the view
is a temporary value which is constructed and thrown away immediately.