I'm new to Rust, and still getting used to all the idioms in the language. I want to create an object that uses a random distribution, so I imported the rand and rand_distr crates, and am defining the object as follows:
pub struct Bandit<const K: usize> {
levers: [f32; K],
dist: Box<dyn Distribution<f32>>,
}
The Distribution type is defined in the rand crate here.
The above code is giving me the following error:
error[E0038]: the trait `rand_distr::Distribution` cannot be made into an object
--> src/testbed.rs:8:15
|
8 | dist: Box<dyn Distribution<f32>>,
| ^^^^^^^^^^^^^^^^^^^^^ `rand_distr::Distribution` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> /Users/brendan/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/distributions/distribution.rs:37:8
|
37 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
| ^^^^^^ the trait cannot be made into an object because method `sample` has generic type parameters
My workaround for this is to define my own enum which I can map to a distribution later:
pub enum DistType {
Normal { mean: f32, variance: f32 },
Uniform,
}
impl DistType {
pub fn distribution(&self) -> Box<impl Distribution<f32>> {
match self {
DistType::Normal { mean, variance } => /* return normal */,
DistType::Uniform => /* return uniform */,
}
}
}
However, I don't like this solution for the reasons:
- If I can't store the distribution object, it means I have to create one whenever I need to take random samples. I suspect this will create some performance issues.
- If possible, would like to use
dyninstead ofimpl. There may be many more of these types of distributions. - I would prefer to avoid creating custom types like the enum I defined above because I would like to avoid unnecessary indirection.
Is there a way to persist dyn Trait objects that are not object safe?
- Tried dyn vs impl keywords. Reviewed the semantics of what those error and definitely do not want impl in this case
- Tried searching for ways to persist traits that are not object safe and could not find anything
- Looked for examples in the
rand_distrcrate, but all the examples create local distribution variables and use them immediately.