Skip to content

Deprecate rand::rngs::mock module and StepRng #1634

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md).

You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful.

## [Unreleased]
### Deprecated
- Deprecate `rand::rngs::mock` module and `StepRng` generator (#1634)

## [0.9.1] - 2025-04-17
### Security and unsafe
- Revise "not a crypto library" policy again (#1565)
Expand Down
5 changes: 1 addition & 4 deletions benches/benches/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use core::time::Duration;
use criterion::measurement::WallTime;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkGroup, Criterion};
use rand::prelude::*;
use rand::rngs::OsRng;
use rand::rngs::ReseedingRng;
use rand::rngs::{mock::StepRng, OsRng};
use rand_chacha::rand_core::UnwrapErr;
use rand_chacha::{ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Rng};
use rand_pcg::{Pcg32, Pcg64, Pcg64Dxsm, Pcg64Mcg};
Expand Down Expand Up @@ -39,7 +39,6 @@ pub fn random_bytes(c: &mut Criterion) {
});
}

bench(&mut g, "step", StepRng::new(0, 1));
bench(&mut g, "pcg32", Pcg32::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64", Pcg64::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_rng(&mut rand::rng()));
Expand Down Expand Up @@ -68,7 +67,6 @@ pub fn random_u32(c: &mut Criterion) {
});
}

bench(&mut g, "step", StepRng::new(0, 1));
bench(&mut g, "pcg32", Pcg32::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64", Pcg64::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_rng(&mut rand::rng()));
Expand Down Expand Up @@ -97,7 +95,6 @@ pub fn random_u64(c: &mut Criterion) {
});
}

bench(&mut g, "step", StepRng::new(0, 1));
bench(&mut g, "pcg32", Pcg32::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64", Pcg64::from_rng(&mut rand::rng()));
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_rng(&mut rand::rng()));
Expand Down
38 changes: 19 additions & 19 deletions src/distr/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ float_impls! { feature = "simd_support", f64x8, u64x8, f64, u64, 52, 1023 }
#[cfg(test)]
mod tests {
use super::*;
use crate::rngs::mock::StepRng;
use crate::test::const_rng;

const EPSILON32: f32 = f32::EPSILON;
const EPSILON64: f64 = f64::EPSILON;
Expand All @@ -187,30 +187,30 @@ mod tests {
let two = $ty::splat(2.0);

// StandardUniform
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.random::<$ty>(), $ZERO);
let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
let mut one = const_rng(1 << 8 | 1 << (8 + 32));
assert_eq!(one.random::<$ty>(), $EPSILON / two);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(max.random::<$ty>(), $ty::splat(1.0) - $EPSILON / two);

// OpenClosed01
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), $ZERO + $EPSILON / two);
let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
let mut one = const_rng(1 << 8 | 1 << (8 + 32));
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + $ty::splat(1.0));

// Open01
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.sample::<$ty, _>(Open01), $ZERO + $EPSILON / two);
let mut one = StepRng::new(1 << 9 | 1 << (9 + 32), 0);
let mut one = const_rng(1 << 9 | 1 << (9 + 32));
assert_eq!(
one.sample::<$ty, _>(Open01),
$EPSILON / two * $ty::splat(3.0)
);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(
max.sample::<$ty, _>(Open01),
$ty::splat(1.0) - $EPSILON / two
Expand All @@ -235,30 +235,30 @@ mod tests {
let two = $ty::splat(2.0);

// StandardUniform
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.random::<$ty>(), $ZERO);
let mut one = StepRng::new(1 << 11, 0);
let mut one = const_rng(1 << 11);
assert_eq!(one.random::<$ty>(), $EPSILON / two);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(max.random::<$ty>(), $ty::splat(1.0) - $EPSILON / two);

// OpenClosed01
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), $ZERO + $EPSILON / two);
let mut one = StepRng::new(1 << 11, 0);
let mut one = const_rng(1 << 11);
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + $ty::splat(1.0));

// Open01
let mut zeros = StepRng::new(0, 0);
let mut zeros = const_rng(0);
assert_eq!(zeros.sample::<$ty, _>(Open01), $ZERO + $EPSILON / two);
let mut one = StepRng::new(1 << 12, 0);
let mut one = const_rng(1 << 12);
assert_eq!(
one.sample::<$ty, _>(Open01),
$EPSILON / two * $ty::splat(3.0)
);
let mut max = StepRng::new(!0, 0);
let mut max = const_rng(!0);
assert_eq!(
max.sample::<$ty, _>(Open01),
$ty::splat(1.0) - $EPSILON / two
Expand Down
12 changes: 5 additions & 7 deletions src/distr/uniform_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,14 @@ uniform_float_impl! { feature = "simd_support", f64x8, u64x8, f64, u64, 64 - 52
mod tests {
use super::*;
use crate::distr::{utils::FloatSIMDScalarUtils, Uniform};
use crate::rngs::mock::StepRng;
use crate::test::{const_rng, step_rng};

#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_floats() {
let mut rng = crate::test::rng(252);
let mut zero_rng = StepRng::new(0, 0);
let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0);
let mut zero_rng = const_rng(0);
let mut max_rng = const_rng(0xffff_ffff_ffff_ffff);
macro_rules! t {
($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{
let v: &[($f_scalar, $f_scalar)] = &[
Expand Down Expand Up @@ -318,10 +318,8 @@ mod tests {
// since for those rounding might result in selecting high for a very
// long time.
if (high_scalar - low_scalar) > 0.0001 {
let mut lowering_max_rng = StepRng::new(
0xffff_ffff_ffff_ffff,
(-1i64 << $bits_shifted) as u64,
);
let mut lowering_max_rng =
step_rng(0xffff_ffff_ffff_ffff, (-1i64 << $bits_shifted) as u64);
assert!(
<$ty as SampleUniform>::Sampler::sample_single(
low,
Expand Down
28 changes: 28 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,34 @@ mod test {
rand_pcg::Pcg32::new(seed, INC)
}

/// Construct a generator yielding a constant value
pub fn const_rng(x: u64) -> StepRng {
StepRng(x, 0)
}

/// Construct a generator yielding an arithmetic sequence
pub fn step_rng(x: u64, increment: u64) -> StepRng {
StepRng(x, increment)
}

#[derive(Clone)]
pub struct StepRng(u64, u64);
impl RngCore for StepRng {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}

fn next_u64(&mut self) -> u64 {
let res = self.0;
self.0 = self.0.wrapping_add(self.1);
res
}

fn fill_bytes(&mut self, dst: &mut [u8]) {
rand_core::impls::fill_bytes_via_next(self, dst)
}
}

#[test]
#[cfg(feature = "thread_rng")]
fn test_random() {
Expand Down
15 changes: 7 additions & 8 deletions src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ pub trait Rng: RngCore {
/// # Example
///
/// ```
/// use rand::{rngs::mock::StepRng, Rng};
/// use rand::{rngs::SmallRng, Rng, SeedableRng};
///
/// let rng = StepRng::new(1, 1);
/// let rng = SmallRng::seed_from_u64(0);
/// let v: Vec<i32> = rng.random_iter().take(5).collect();
/// assert_eq!(&v, &[1, 2, 3, 4, 5]);
/// assert_eq!(v.len(), 5);
/// ```
#[inline]
fn random_iter<T>(self) -> distr::Iter<StandardUniform, Self, T>
Expand Down Expand Up @@ -479,14 +479,13 @@ where
#[cfg(test)]
mod test {
use super::*;
use crate::rngs::mock::StepRng;
use crate::test::rng;
use crate::test::{const_rng, rng};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;

#[test]
fn test_fill_bytes_default() {
let mut r = StepRng::new(0x11_22_33_44_55_66_77_88, 0);
let mut r = const_rng(0x11_22_33_44_55_66_77_88);

// check every remainder mod 8, both in small and big vectors.
let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87];
Expand All @@ -507,7 +506,7 @@ mod test {
#[test]
fn test_fill() {
let x = 9041086907909331047; // a random u64
let mut rng = StepRng::new(x, 0);
let mut rng = const_rng(x);

// Convert to byte sequence and back to u64; byte-swap twice if BE.
let mut array = [0u64; 2];
Expand Down Expand Up @@ -537,7 +536,7 @@ mod test {
#[test]
fn test_fill_empty() {
let mut array = [0u32; 0];
let mut rng = StepRng::new(0, 1);
let mut rng = rng(1);
rng.fill(&mut array);
rng.fill(&mut array[..]);
}
Expand Down
31 changes: 4 additions & 27 deletions src/rngs/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

//! Mock random number generator

#![allow(deprecated)]

use rand_core::{impls, RngCore};

#[cfg(feature = "serde")]
Expand All @@ -31,6 +33,7 @@ use serde::{Deserialize, Serialize};
/// # Example
///
/// ```
/// # #![allow(deprecated)]
/// use rand::Rng;
/// use rand::rngs::mock::StepRng;
///
Expand All @@ -40,6 +43,7 @@ use serde::{Deserialize, Serialize};
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[deprecated(since = "0.9.2", note = "Deprecated without replacement")]
pub struct StepRng {
v: u64,
a: u64,
Expand Down Expand Up @@ -74,30 +78,3 @@ impl RngCore for StepRng {
impls::fill_bytes_via_next(self, dst)
}
}

#[cfg(test)]
mod tests {
#[cfg(any(feature = "alloc", feature = "serde"))]
use super::StepRng;

#[test]
#[cfg(feature = "serde")]
fn test_serialization_step_rng() {
let some_rng = StepRng::new(42, 7);
let de_some_rng: StepRng =
bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap();
assert_eq!(some_rng.v, de_some_rng.v);
assert_eq!(some_rng.a, de_some_rng.a);
}

#[test]
#[cfg(feature = "alloc")]
fn test_bool() {
use crate::{distr::StandardUniform, Rng};

// If this result ever changes, update doc on StepRng!
let rng = StepRng::new(0, 1 << 31);
let result: alloc::vec::Vec<bool> = rng.sample_iter(StandardUniform).take(6).collect();
assert_eq!(&result, &[false, true, false, true, false, true]);
}
}
1 change: 1 addition & 0 deletions src/rngs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
mod reseeding;
pub use reseeding::ReseedingRng;

#[deprecated(since = "0.9.2")]
pub mod mock; // Public so we don't export `StepRng` directly, making it a bit
// more clear it is intended for testing.

Expand Down
6 changes: 3 additions & 3 deletions src/rngs/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,15 @@ where
#[cfg(feature = "std_rng")]
#[cfg(test)]
mod test {
use crate::rngs::mock::StepRng;
use crate::rngs::std::Core;
use crate::test::const_rng;
use crate::Rng;

use super::ReseedingRng;

#[test]
fn test_reseeding() {
let zero = StepRng::new(0, 0);
let zero = const_rng(0);
let thresh = 1; // reseed every time the buffer is exhausted
let mut reseeding = ReseedingRng::<Core, _>::new(thresh, zero).unwrap();

Expand All @@ -281,7 +281,7 @@ mod test {
#[test]
#[allow(clippy::redundant_clone)]
fn test_clone_reseeding() {
let zero = StepRng::new(0, 0);
let zero = const_rng(0);
let mut rng1 = ReseedingRng::<Core, _>::new(32 * 4, zero).unwrap();

let first: u32 = rng1.random();
Expand Down