I am aware that there are many similar questions, but it seems to me that the error in my case is the opposite of what I read in the other questions.
I wrote a function that creates a random generator from a seed (if given), another generator (if given) or the thread generator:
use rand::{RngCore, SeedableRng, thread_rng};
use rand_pcg::Pcg64Mcg;
pub fn get_rng<R: RngCore>(parent: Option<R>, seed: Option<u64>) -> Pcg64Mcg {
match seed {
Some(s) => Pcg64Mcg::seed_from_u64(s),
None => {
let parent = parent.unwrap_or_else(|| thread_rng() as dyn RngCore); // error here
Pcg64Mcg::from_rng(parent).expect("failed to seed random generator")
}
}
}
The code does not compile because the compiler expects the variable parent
to be of type R
, but it finds the concrete type ThreadRng
:
error[E0308]: mismatched types
--> src/utils.rs:13:51
|
9 | pub fn get_rng<R: RngCore>(parent: Option<R>, seed: Option<u64>) -> Pcg64Mcg {
| - this type parameter
...
13 | let parent = parent.unwrap_or_else(|| thread_rng());
| ^^^^^^^^^^^^ expected type parameter `R`, found struct `rand::prelude::ThreadRng`
|
= note: expected type parameter `R`
found struct `rand::prelude::ThreadRng`
Ok, that makes sense, so let's inform the compiler that it should interpret ThreadRng
as RngCore
:
-
thread_rng() as dyn RngCore
error: cast to unsized type -
thread_rng() as dyn RngCore + Sized
error: only auto traits can be used as additional traits in a trait object -
thread_rng() as R
error: non-primitive cast
The point is that the compiler wants parent
to be of type R
, i.e. something that implements RngCore
; well, ThreadRng
does implement that, so why doesn't it work? The similar error that I have seen are the opposite: they usually involve function arguments and the compiler gives an error because the generic type parameter covers more cases that the programmer thought about and it cannot guarantee that all of them will work. Here it's a single case and I know it works, since ThreadRng
implements RngCore
.
As a matter of fact, directly passing thread_rng()
as the parent
argument works fine, so I really think I'm missing something obvious.