I am trying to implement part of a UI framework. In the bottom example, the impl of widgets_mut()
for Vec<T>
needs to return a vector of trait objects like Vec<&mut dyn AnyWidget>
. Given T is constrained to impl AnyWidget
I don't understand why I am getting the error:
a value of type `Vec<&mut dyn AnyWidget>` cannot be built from an iterator over elements of type `&mut T`
the trait `FromIterator<&mut T>` is not implemented for `Vec<&mut dyn AnyWidget>`
Why does the 2-tuple implementation work, but the Vec implementation which seems equivalent doesn't?
fn main() {}
pub trait AnyWidget {}
pub trait WidgetVec {
fn widgets_mut(&mut self) -> Vec<&mut dyn AnyWidget>;
}
// This implementation for a 2-tuple seems equivalent and works fine:
impl<W0: AnyWidget, W1: AnyWidget> WidgetVec for (W0, W1) {
fn widgets_mut(&mut self) -> Vec<&mut dyn AnyWidget> {
let mut v: Vec<&mut dyn AnyWidget> = Vec::with_capacity(2);
v.push(&mut self.0);
v
}
}
impl<T: AnyWidget> WidgetVec for Vec<T> {
fn widgets_mut(&mut self) -> Vec<&mut dyn AnyWidget> {
self.iter_mut()
.map(|child| child)
.collect::<Vec<&mut dyn AnyWidget>>()
}
}
All you're missing is to explicitly cast the child
from &mut T
to &mut dyn AnyWidget
.
impl<T: AnyWidget> WidgetVec for Vec<T> {
fn widgets_mut(&mut self) -> Vec<&mut dyn AnyWidget> {
self.iter_mut()
.map(|child| child as &mut dyn AnyWidget)
.collect::<Vec<&mut dyn AnyWidget>>()
}
}
In some cases, rust will perform these kinds of conversions automatically (at "coercion sites"), but this can't be done here, because there isn't a coercion site where you're trying to cast child
. See the reference on coercion sites for all the places this can be done.