Skip to content

Commit

Permalink
rand_core: add blanket impl of TryRngCore for RngCore (#1499)
Browse files Browse the repository at this point in the history
This PR removes the hacky `impl_try_rng_from_rng_core` and
`impl_try_crypto_rng_from_crypto_rng` macros and replaces them with
blanket impls of `TryRngCore` for `RngCore` and `TryCryptoRng` for
`CryptoRng`.

This change means that `TryRngCore`/`TryCryptoRng` no longer can have
blanket impls for `&mut R` and `Box<R>`. But I think it should be
tolerable since most users will be using `RngCore`/`CryptoRng`, which
have blanket impl for `DerefMut` (it covers both `&mut R` and `Box<R>`).
  • Loading branch information
newpavlov authored Oct 9, 2024
1 parent 9c2787d commit 0fba940
Show file tree
Hide file tree
Showing 17 changed files with 75 additions and 184 deletions.
8 changes: 4 additions & 4 deletions benches/benches/seq_choose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ criterion_main!(benches);

pub fn bench(c: &mut Criterion) {
c.bench_function("seq_slice_choose_1_of_100", |b| {
let mut rng = Pcg32::from_rng(thread_rng());
let mut rng = Pcg32::from_rng(&mut thread_rng());
let mut buf = [0i32; 100];
rng.fill(&mut buf);
let x = black_box(&mut buf);
Expand All @@ -32,7 +32,7 @@ pub fn bench(c: &mut Criterion) {
for (amount, len) in lens {
let name = format!("seq_slice_choose_multiple_{}_of_{}", amount, len);
c.bench_function(name.as_str(), |b| {
let mut rng = Pcg32::from_rng(thread_rng());
let mut rng = Pcg32::from_rng(&mut thread_rng());
let mut buf = [0i32; 1000];
rng.fill(&mut buf);
let x = black_box(&buf[..len]);
Expand All @@ -53,15 +53,15 @@ pub fn bench(c: &mut Criterion) {
}

c.bench_function("seq_iter_choose_multiple_10_of_100", |b| {
let mut rng = Pcg32::from_rng(thread_rng());
let mut rng = Pcg32::from_rng(&mut thread_rng());
let mut buf = [0i32; 100];
rng.fill(&mut buf);
let x = black_box(&buf);
b.iter(|| x.iter().cloned().choose_multiple(&mut rng, 10))
});

c.bench_function("seq_iter_choose_multiple_fill_10_of_100", |b| {
let mut rng = Pcg32::from_rng(thread_rng());
let mut rng = Pcg32::from_rng(&mut thread_rng());
let mut buf = [0i32; 100];
rng.fill(&mut buf);
let x = black_box(&buf);
Expand Down
2 changes: 1 addition & 1 deletion benches/benches/shuffle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ criterion_main!(benches);

pub fn bench(c: &mut Criterion) {
c.bench_function("seq_shuffle_100", |b| {
let mut rng = Pcg32::from_rng(thread_rng());
let mut rng = Pcg32::from_rng(&mut thread_rng());
let mut buf = [0i32; 100];
rng.fill(&mut buf);
let x = black_box(&mut buf);
Expand Down
4 changes: 2 additions & 2 deletions benches/benches/uniform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const N_RESAMPLES: usize = 10_000;
macro_rules! sample {
($R:ty, $T:ty, $U:ty, $g:expr) => {
$g.bench_function(BenchmarkId::new(stringify!($R), "single"), |b| {
let mut rng = <$R>::from_rng(thread_rng());
let mut rng = <$R>::from_rng(&mut thread_rng());
let x = rng.random::<$U>();
let bits = (<$T>::BITS / 2);
let mask = (1 as $U).wrapping_neg() >> bits;
Expand All @@ -35,7 +35,7 @@ macro_rules! sample {
});

$g.bench_function(BenchmarkId::new(stringify!($R), "distr"), |b| {
let mut rng = <$R>::from_rng(thread_rng());
let mut rng = <$R>::from_rng(&mut thread_rng());
let x = rng.random::<$U>();
let bits = (<$T>::BITS / 2);
let mask = (1 as $U).wrapping_neg() >> bits;
Expand Down
4 changes: 2 additions & 2 deletions benches/benches/uniform_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const N_RESAMPLES: usize = 10_000;
macro_rules! single_random {
($R:ty, $T:ty, $g:expr) => {
$g.bench_function(BenchmarkId::new(stringify!($T), stringify!($R)), |b| {
let mut rng = <$R>::from_rng(thread_rng());
let mut rng = <$R>::from_rng(&mut thread_rng());
let (mut low, mut high);
loop {
low = <$T>::from_bits(rng.random());
Expand Down Expand Up @@ -63,7 +63,7 @@ fn single_random(c: &mut Criterion) {
macro_rules! distr_random {
($R:ty, $T:ty, $g:expr) => {
$g.bench_function(BenchmarkId::new(stringify!($T), stringify!($R)), |b| {
let mut rng = <$R>::from_rng(thread_rng());
let mut rng = <$R>::from_rng(&mut thread_rng());
let dist = loop {
let low = <$T>::from_bits(rng.random());
let high = <$T>::from_bits(rng.random());
Expand Down
2 changes: 1 addition & 1 deletion benches/benches/weighted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub fn bench(c: &mut Criterion) {
c.bench_function(name.as_str(), |b| {
let length = black_box(length);
let amount = black_box(amount);
let mut rng = SmallRng::from_rng(thread_rng());
let mut rng = SmallRng::from_rng(&mut thread_rng());
b.iter(|| sample_weighted(&mut rng, length, |idx| (1 + (idx % 100)) as u32, amount))
});
}
Expand Down
2 changes: 0 additions & 2 deletions rand_chacha/src/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ macro_rules! chacha_impl {

impl CryptoRng for $ChaChaXRng {}

rand_core::impl_try_crypto_rng_from_crypto_rng!($ChaChaXRng);

impl From<$ChaChaXCore> for $ChaChaXRng {
fn from(core: $ChaChaXCore) -> Self {
$ChaChaXRng {
Expand Down
88 changes: 0 additions & 88 deletions rand_core/src/blanket_impls.rs

This file was deleted.

8 changes: 4 additions & 4 deletions rand_core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
}

#[inline(always)]
fn from_rng(rng: impl RngCore) -> Self {
fn from_rng(rng: &mut impl RngCore) -> Self {
Self::new(R::from_rng(rng))
}

#[inline(always)]
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
fn try_from_rng<S: TryRngCore>(rng: &mut S) -> Result<Self, S::Error> {
R::try_from_rng(rng).map(Self::new)
}
}
Expand Down Expand Up @@ -415,12 +415,12 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
}

#[inline(always)]
fn from_rng(rng: impl RngCore) -> Self {
fn from_rng(rng: &mut impl RngCore) -> Self {
Self::new(R::from_rng(rng))
}

#[inline(always)]
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
fn try_from_rng<S: TryRngCore>(rng: &mut S) -> Result<Self, S::Error> {
R::try_from_rng(rng).map(Self::new)
}
}
Expand Down
54 changes: 0 additions & 54 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,60 +160,6 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
u64::from_le_bytes(buf)
}

/// Implement [`TryRngCore`][crate::TryRngCore] for a type implementing [`RngCore`].
///
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
/// have to implement `TryRngCore` directly.
#[macro_export]
macro_rules! impl_try_rng_from_rng_core {
($t:ty) => {
impl $crate::TryRngCore for $t {
type Error = core::convert::Infallible;

#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok($crate::RngCore::next_u32(self))
}

#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok($crate::RngCore::next_u64(self))
}

#[inline]
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
$crate::RngCore::fill_bytes(self, dst);
Ok(())
}
}
};
}

/// Implement [`TryCryptoRng`] and [`TryRngCore`] for a type implementing [`CryptoRng`].
///
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
/// have to implement `TryRngCore` and `TryCryptoRng` directly.
///
/// [`TryCryptoRng`]: crate::TryCryptoRng
/// [`TryRngCore`]: crate::TryRngCore
/// [`CryptoRng`]: crate::CryptoRng
#[macro_export]
macro_rules! impl_try_crypto_rng_from_crypto_rng {
($t:ty) => {
$crate::impl_try_rng_from_rng_core!($t);

impl $crate::TryCryptoRng for $t {}

/// Check at compile time that `$t` implements `CryptoRng`
const _: () = {
const fn check_crypto_rng_impl<T: $crate::CryptoRng>() {}
check_crypto_rng_impl::<$t>();
};
};
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading

0 comments on commit 0fba940

Please sign in to comment.