Using trait objects with non-object-safe library trait (rand_distr::DIstribution)

Context
I'm trying to build a list of Distribution<T>s in a library that consumes said distributions. I'd like to use rand_distr::Distribution to accept any trait object that implements Distribution in my collection.

Ultimately, what I want to do is push() any instance of a struct that implements Distribution, such as Normal, then go through every entry in my Vec and call sample().

Problem
If I try to use a Vec<dyn Distribution<T>>, I'm met with an error that tells me I can't do this because the trait is not object safe. This makes sense, because the function I want to use from the trait, sample() is generic over R: Rng. However, I know exactly what Rng I want to use, so I don't want to compiler to monomorphise the function for multiple types of Rng.

Is there some way for me to tell this to the compiler? I think it might be possible if there was an associated type defined in sample()?

You can make a new trait that wraps the other trait.

trait FixedRngDistribution<T> {
    fn sample(&self);
}

impl<T, U> FixedRngDistribution<T> for U where U: Distribution<T> {
    fn sample(&self) {
        <Self as Distribution<T>>::sample::<SomeRng>(self)
    }
}

Making SomeRng an associated type in your new trait is an option too (though it will show up in your dyn types).

2 Likes

Thanks @quinedot, that did the trick!
I also ended up using the dyn-clone crate to generate a Clone impl for my Box<dyn Distribution>.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.