I have a trait Storage
which is implemented by various types:
pub trait Storage {
fn new() -> Self;
fn push(&mut self, n: u32) -> ();
}
pub struct HeapStorage { inner: Vec<u32> }
impl Storage for HeapStorage {
fn new() -> Self {
Self { inner: Vec::with_capacity(100) }
}
fn push(&mut self, n: u32) { self.inner.push(n); }
}
pub struct StackStorage { inner: [u32; 100], pos: usize }
impl Storage for StackStorage {
fn new() -> Self {
Self { inner: [0; 100], pos: 0 }
}
fn push(&mut self, n: u32) {
self.inner[self.pos] = n;
self.pos += 1;
}
}
And a generic type Loader
which operates on Storage
s:
pub struct Loader<S: Storage> { storage: S }
impl<S: Storage> Loader<S> {
pub fn new() -> Self {
Self { storage: S::new() }
}
pub fn load(&mut self) {
for n in 0..100 {
self.storage.push(n);
}
}
}
So far so good! But what I'd really like is for Loader
to contain a BorrowMut<Storage>
, and provide methods to either create a new Loader
with its own owned Storage
, or to provide an existing &mut Storage
:
pub struct BetterLoader<S: BorrowMut<Storage>> { storage: S }
impl<S: Storage> BetterLoader<S> {
pub fn new() -> Self {
Self { storage: S::new() }
}
pub fn from_storage(storage: S) -> Self {
Self { storage }
}
pub fn load(&mut self) {
for n in 0..100 {
self.storage.borrow_mut().push(n);
}
}
}
The compiler doesn't like the above example:
error[E0782]: trait objects must include the `dyn` keyword
|
58 | pub struct BetterLoader<S: BorrowMut<Storage>> {
| ^^^^^^^
help: add `dyn` keyword before this trait
|
58 | pub struct BetterLoader<S: BorrowMut<dyn Storage>> {
It's not a trait object I'm after ideally.
I've also tried various other permutations, and always hit an error one way or another. Is there any way to achieve something like this?
I'm sure this question has come up before, but I've been unable to find it - probably because I don't know what this pattern would be called (nested generic?), and so what search terms to use. Please excuse the repetition.