Option<&mut dyn Trait>

Hi fellas I'm a little bit puzzled with this one and asking for your help.

use rand;

trait Material {
     fn calculate(&self, data: &mut Data, rng: Option<&mut dyn rand::RngCore>)
}

impl Material for Foo {
    fn calculate(&self, data: &mut Data, rng: Option<&mut dyn rand::RngCore>) {
        // How to use use the Some part of the Option or create a new one (rand::thread_rng()) if it's None?
       // Avoiding unnecessary allocations of course.
       let mut rng = ?
    }
}

I tried with Cow:

       let rng = rng.map_or_else(||Cow::Owned(rand::thread_rng()), |v| Cow::Borrow(v));
error[E0271]: type mismatch resolving `<dyn rand_core::RngCore as std::borrow::ToOwned>::Owned == rand::rngs::thread::ThreadRng`
   |
21 |         let mut rng= rng.map_or_else(||Cow::Owned(rand::thread_rng()), |v| Cow::Borrowed(v));
   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn rand_core::RngCore`, found struct `rand::rngs::thread::ThreadRng`
   |
   = note: expected type `dyn rand_core::RngCore`
            found struct `rand::rngs::thread::ThreadRng`

What is the best way to solve this?
I'm using dyn rand::RngCore instead of a generic parameter, because the calculate is a trait object method and we can't have trait objects with generics. Please correct me if I'm wrong.

This works.

let mut trng: rand::rngs::ThreadRng;
let mut rng = match rng {
    Some(rng) => rng,
    None => {
        trng = rand::thread_rng();
        &mut trng
    }
};

But the creation of the ThreadRng is not expensive - it's just a handle to the thread-local cached RNG. So unconditionally calls rand::threa_rng() wouldn't be bad.

Thank you! That works. I forgot that sometimes uninitialized variables are useful in Rust :slightly_smiling_face:
This code is in a very tight loop, so I’m trying to optimize it as much as possible.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.