I have two related traits List
and ListItem
(playground link).
trait List {
type Item: ListItem;
fn items(&self) -> Vec<Self::Item>;
/* more stuff */
}
where Item
is an associated type on List
and ListItem
has a custom implementation for PartialEq
and Debug
Inside of a List
trait method that looks like
fn foo(&self, other: &dyn List<Item=Self::Item>)
I would like to compare sub-slices of the items, using the PartialEq
defined for ListItem
.
e.g.
let lhs: &[&dyn ListItem] = ...;
let rhs: &[&dyn ListItem] = ...;
assert_eq!(lhs, rhs);
but I cannot coerce the slices to the correct type.
fn foo(&self, other: &dyn List<Item = Self::Item>) {
let items = self.items();
let items_slice: &[&dyn ListItem] = items.as_slice(); // <-- Error here
error[E0308]: mismatched types
|
40 | let these: &[&dyn ListItem] = these_items.as_slice();
| ---------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `&[&dyn ListItem]`, found `&[<Self as List>::Item]`
| |
| expected due to this
|
= note: expected reference `&[&dyn ListItem]`
found reference `&[<Self as List>::Item]`
= help: consider constraining the associated type `<Self as List>::Item` to `&dyn ListItem`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
How can I coerce the slice to the correct type?
You cannot. First, you need references, and items
contains owned items. Second, you need fat references, and items
has concrete types.
You need to collect them into a Vec
:
let items = self.items();
let items_dyn = items
.iter()
.map(|item| item as &dyn ListItem)
.collect::<Vec<_>>();