I am trying to store a boxed list of a dyn trait A
and then implement an extension trait to make it easy to retrieve a particular impl of A
. My helper trait returns &Box<dyn A>
but clippy is yelling at me telling me not to use &Box
For example, I have a trait like Foo
and multiple implementations
trait Foo {
fn matches(&self, b: &Bar) -> bool;
fn do_thing(&self, b: &Bar);
}
// Assume several impl's of Foo called Fiz, Fuz, and Fez
let foos: Vec<Box<dyn Foo>> = vec![
Box::new(Fiz::new(...)),
Box::new(Fuz::new(...)),
Box::new(Fez::new(...)),
];
I then try to define a helper trait like
pub trait FindFoo {
fn find_foo(b: Bar) -> Option<&Box<dyn Foo>>;
}
impl FindFoo for Vec<Box<dyn Foo>> {
fn find_foo(&self, bar: &Bar) -> Option<&Box<dyn Foo>> {
self.iter().find(|foo| foo.matches(bar))
}
}
This works, but clippy is telling me
you seem to be trying to use `&Box<T>`. Consider using just `&T`
`#[warn(clippy::borrowed_box)]` on by default
for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
If I remove the reference from the return type I get all kinds of errors. For example,
// Updating the trait and leaving out the boilerplate
fn find_foo(&self, b: &Bar) -> Option<Box<dyn Foo>> {
self.iter().find(|foo| foo.matches(bar)).as_deref()
}
Results in the mismatches types error
mismatched types
expected enum `std::option::Option<std::boxed::Box<(dyn Foo + 'static)>>`
found enum `std::option::Option<&std::boxed::Box<dyn Foo>>`
I've considered cloning (Option::cloned
) and copying (Option::copied
) but these don't really solve the problem. Do I need to to use an Rc
here so my vec can keep a reference to my dyn Foo
on the heap and hand out a reference as needed?
Any tips on a better way to do this is appreciated Thank you!