I have a vector of dynamic dispatch references that implement an extended trait. I would also like to be able to pass them in to a function that accepts the base trait:
use std::borrow::BorrowMut;
trait MyTrait {
fn doit(&mut self);
}
trait MyOtherTrait: MyTrait {
fn doit_too(&mut self);
}
fn doit<T>(items: &mut [T])
where T: BorrowMut<dyn MyTrait>
{
for item in items.iter_mut() {
item.borrow_mut().doit();
}
}
struct A {}
impl MyTrait for A {
fn doit(&mut self) { println!("AAAAA!"); }
}
impl MyOtherTrait for A {
fn doit_too(&mut self) { println!("22222!"); }
}
fn main() {
let mut boxes: Vec<Box<dyn MyOtherTrait>> = vec![A{}, A{}, A{}].into_iter().map(|a| Box::new(a) as Box<dyn MyOtherTrait>).collect();
doit(&mut boxes);
for item in boxes.iter_mut() {
item.doit_too();
}
}
error[E0277]: the trait bound `Box<dyn MyOtherTrait>: BorrowMut<(dyn MyTrait + 'static)>` is not satisfied
--> src/main-dyn.rs:31:10
|
31 | doit(&mut boxes);
| ---- ^^^^^^^^^^ the trait `BorrowMut<(dyn MyTrait + 'static)>` is not implemented for `Box<dyn MyOtherTrait>`
| |
| required by a bound introduced by this call
|
= help: the trait `BorrowMut<dyn MyOtherTrait>` is implemented for `Box<dyn MyOtherTrait>`
note: required by a bound in `doit`
--> src/main-dyn.rs:12:10
|
11 | fn doit<T>(items: &mut [T])
| ---- required by a bound in this function
12 | where T: BorrowMut<dyn MyTrait>
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `doit`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `scratchpad` (bin "dyn") due to previous error
Where is the lifetime requirement 'static
coming from? How can I process the vector of MyOtherTrait
boxes as MyTrait
?
For reference, I have tried to make a second vector Vec<&mut dyn MyTrait>
from boxes
, but that results in multiple mutable borrows when I call the function.
You can relax your requirements in doit
to this:
fn doit<T, U>(items: &mut [T])
where
T: AsMut<U>,
U: MyTrait + ?Sized,
{
for item in items.iter_mut() {
item.as_mut().doit();
}
}
By not requiring it to give you dyn MyTrait
directly, just anything that can produce a mutable reference to something that implements the trait, you can pass trait objects to things that implement a super trait as well.