How can I use a trait from a transitive dependency crate in my application?
Here's a minimal illustrative example of the problem I've run into:
In Cargo.toml
, I have:
[dependencies]
mersenne_twister = "1.1.1"
rand = "0.8.5"
My crate depends on rand ^0.8.5
and mersenne_twister ^1.1.1
, which itself depends on rand >=0.3, <0.5
:
my-crate ---> rand 0.8.5
|
|
---> mersenne_twister 1.1.1 ----> rand >= 0.3, < 0.5
In my app, I'd like to use the implementation of trait rand::Rng for mersenne_twister::MT19937
. But when I try bringing this trait into scope, it's apparently not recognized:
use mersenne_twister::MT19937;
use rand::Rng;
fn main() {
let mut rng = MT19937::new_unseeded();
let mut buffer = vec![0; 0xFFFF];
// error[E0599]: no method named `fill_bytes` found for struct `MT19937` in the current scope
rng.fill_bytes(&mut buffer);
}
My guess is that the Rng
trait imported by use rand::Rng;
is the one from rand 0.8.5
, not the one from rand 0.4.6
that is actually implemented for MT19937
, and that even though they are spelled the same way, they are distinct and unrelated traits and therefore cannot be referenced interchangeably.
So I have some questions:
Rng
trait that works for MT19937
in my app? I don't think I can downgrade my dependency on rand
to 0.4.6
in Cargo.toml
because I need to use rand 0.8.5
elsewere in my app.mersenne_twister
's API design bad practice for not re-exporting Rng
?You can add multiple incompatible versions of a dependency to Cargo.toml by renaming one of them.
[dependencies]
mersenne_twister = "1.1.1"
rand = "0.8.5"
old_rand = { package = "rand", version = "0.4.6" }
But for this situation, there's already a better solution: use the MT19937 crate, which depends on the latest version of rand_core. RNG implementations should depend on rand_core instead of rand since all they need is the Rng
trait and not any of the extras in rand, like distributions.