Is there a way to get a mutable reference to a dyn trait inside a vector?

Hi there!

I'm new to Rust and I'm struggling with mutability and borrowing. Probably my issue has been asked several times but I can't find an answer suitable to my use case.

What I'm trying to do is to have a function to configure a vector of traits, then in the caller function I would like to execute the resulting traits' logic.

I simplified my code as follows:

trait MyTrait {
    fn apply(&mut self);
}

struct Foo {}
impl MyTrait for Foo {
    fn apply(&mut self) {

    }
}

struct Bar {}
impl MyTrait for Bar {
    fn apply(&mut self) {

    }
}

fn my_fn() {
    let vec = get_vec();
    for i in (0..1000).into_iter() {
        vec.get(0).unwrap().apply();
    }
}

fn get_vec() -> Vec<Box<dyn MyTrait>> {
    let mut res: Vec<Box<dyn MyTrait>> = vec![];

    let mut foo = Foo{};
    res.push(Box::new(foo));

    let mut bar = Bar{};
    res.push(Box::new(bar));

    res
}

The compiler stops me with the message

cannot borrow data in a & reference as mutable
| vec.get(0).unwrap().apply();
| ^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

Is there a way to obtain a mutable reference to the items of the vector?

I decided to proceed in this way in order to execute the configuration only one time and then apply the logic for each required iteration. Probably I'm applying a wrong pattern coming from the OOP world, so I would appreciate also a hint that point me in the right direction to change my mind if needed

I believe you're looking for Vec::get_mut

let mut vec = get_vec();
for i in (0..1000).into_iter() {
    vec.get_mut(0).unwrap().apply();
}

Or, instead of unwrapping, you can use indexing instead:

let mut vec = get_vec();
for i in (0..1000).into_iter() {
    vec[0].apply();
}
2 Likes

One quick note

What you have is a vector of trait objects. You can't have a vector of traits, because traits are not types. Getting the language correct can help a lot when searching.

Separately, I'm also a bit suspicious that you really need a vector of trait objects. Have you considered an enum instead? If you only need to store a closed set of types, an enum would probably be a better choice. Trait objects would only be necessary if the set of types is completely open, and you expect the vector to contain user-defined types as well. It's hard to tell without more information though.

1 Like