Merge pull request #319 from dhardy/generics
Generics
diff --git a/benches/misc.rs b/benches/misc.rs
index ccb10fd..7b6e33a 100644
--- a/benches/misc.rs
+++ b/benches/misc.rs
@@ -38,7 +38,7 @@
#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
- let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &mut [usize] = &mut [1; 100];
b.iter(|| {
rng.shuffle(x);
@@ -48,7 +48,7 @@
#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
- let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 100];
b.iter(|| {
black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e));
@@ -57,7 +57,7 @@
#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
- let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 100];
b.iter(|| {
black_box(sample_slice(&mut rng, x, 10));
@@ -66,7 +66,7 @@
#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
- let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
let x : &[usize] = &[1; 100];
b.iter(|| {
black_box(sample_slice_ref(&mut rng, x, 10));
@@ -77,7 +77,7 @@
($name:ident, $amount:expr, $length:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
- let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
b.iter(|| {
black_box(sample_indices(&mut rng, $length, $amount));
})
diff --git a/rand-core/src/impls.rs b/rand-core/src/impls.rs
index d5979be..2f5a96c 100644
--- a/rand-core/src/impls.rs
+++ b/rand-core/src/impls.rs
@@ -323,7 +323,7 @@
}
}
- fn from_rng<RNG: RngCore>(rng: &mut RNG) -> Result<Self, Error> {
+ fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
let results_empty = R::Results::default();
Ok(Self {
core: R::from_rng(rng)?,
diff --git a/rand-core/src/lib.rs b/rand-core/src/lib.rs
index 1c997d5..e11b3e7 100644
--- a/rand-core/src/lib.rs
+++ b/rand-core/src/lib.rs
@@ -317,7 +317,7 @@
/// [`NewRng`]: https://docs.rs/rand/0.5/rand/trait.NewRng.html
/// [`OsRng`]: https://docs.rs/rand/0.5/rand/os/struct.OsRng.html
/// [`XorShiftRng`]: https://docs.rs/rand/0.5/rand/prng/xorshift/struct.XorShiftRng.html
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
+ fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
diff --git a/src/distributions/other.rs b/src/distributions/other.rs
index 3d797cf..084354d 100644
--- a/src/distributions/other.rs
+++ b/src/distributions/other.rs
@@ -165,7 +165,7 @@
#[test]
fn test_misc() {
- let mut rng: &mut RngCore = &mut ::test::rng(820);
+ let rng: &mut RngCore = &mut ::test::rng(820);
rng.sample::<char, _>(Uniform);
rng.sample::<bool, _>(Uniform);
diff --git a/src/lib.rs b/src/lib.rs
index c4e0ed2..37ef5f2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -332,16 +332,40 @@
/// An automatically-implemented extension trait on [`RngCore`] providing high-level
/// generic methods for sampling values and other convenience methods.
///
-/// This is the primary trait to use when generating random values. Example:
+/// This is the primary trait to use when generating random values.
+///
+/// # Generic usage
+///
+/// The basic pattern is `fn foo<R: Rng + ?Sized>(rng: &mut R)`. Some
+/// things are worth noting here:
+///
+/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no
+/// difference whether we use `R: Rng` or `R: RngCore`.
+/// - The `+ ?Sized` un-bounding allows functions to be called directly on
+/// type-erased references; i.e. `foo(r)` where `r: &mut RngCore`. Without
+/// this it would be necessary to write `foo(&mut r)`.
+///
+/// An alternative pattern is possible: `fn foo<R: Rng>(rng: R)`. This has some
+/// trade-offs. It allows the argument to be consumed directly without a `&mut`
+/// (which is how `from_rng(thread_rng())` works); also it still works directly
+/// on references (including type-erased references). Unfortunately within the
+/// function `foo` it is not known whether `rng` is a reference type or not,
+/// hence many uses of `rng` require an extra reference, either explicitly
+/// (`distr.sample(&mut rng)`) or implicitly (`rng.gen()`); one may hope the
+/// optimiser can remove redundant references later.
+///
+/// Example:
///
/// ```rust
/// use rand::Rng;
///
-/// fn use_rng<R: Rng + ?Sized>(rng: &mut R) -> f32 {
+/// fn foo<R: Rng + ?Sized>(rng: &mut R) -> f32 {
/// rng.gen()
/// }
/// ```
///
+/// # Iteration
+///
/// Iteration over an `Rng` can be achieved using `iter::repeat` as follows:
///
/// ```rust
@@ -635,7 +659,7 @@
}
}
-impl<R: RngCore> Rng for R {}
+impl<R: RngCore + ?Sized> Rng for R {}
/// Trait for casting types to byte slices
///
@@ -800,7 +824,7 @@
///
/// fn foo() -> Result<(), Error> {
/// // This uses StdRng, but is valid for any R: SeedableRng
- /// let mut rng = StdRng::from_rng(&mut EntropyRng::new())?;
+ /// let mut rng = StdRng::from_rng(EntropyRng::new())?;
///
/// println!("random number: {}", rng.gen_range(1, 10));
/// Ok(())
@@ -812,7 +836,7 @@
#[cfg(feature="std")]
impl<R: SeedableRng> NewRng for R {
fn new() -> R {
- R::from_rng(&mut EntropyRng::new()).unwrap_or_else(|err|
+ R::from_rng(EntropyRng::new()).unwrap_or_else(|err|
panic!("NewRng::new() failed: {}", err))
}
}
@@ -860,8 +884,8 @@
StdRng(Hc128Rng::from_seed(seed))
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
- Hc128Rng::from_rng(rng).map(|rng| StdRng(rng))
+ fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
+ Hc128Rng::from_rng(rng).map(|result| StdRng(result))
}
}
@@ -896,14 +920,18 @@
/// efficient:
///
/// ```
+/// use std::iter;
/// use rand::{SeedableRng, SmallRng, thread_rng};
///
/// // Create a big, expensive to initialize and slower, but unpredictable RNG.
/// // This is cached and done only once per thread.
/// let mut thread_rng = thread_rng();
-/// // Create small, cheap to initialize and fast RNG with a random seed.
-/// // This is very unlikely to fail.
-/// let mut small_rng = SmallRng::from_rng(&mut thread_rng).unwrap();
+/// // Create small, cheap to initialize and fast RNGs with random seeds.
+/// // One can generally assume this won't fail.
+/// let rngs: Vec<SmallRng> = iter::repeat(())
+/// .map(|()| SmallRng::from_rng(&mut thread_rng).unwrap())
+/// .take(10)
+/// .collect();
/// ```
///
/// [Xorshift]: struct.XorShiftRng.html
@@ -937,8 +965,8 @@
SmallRng(XorShiftRng::from_seed(seed))
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
- XorShiftRng::from_rng(rng).map(|rng| SmallRng(rng))
+ fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
+ XorShiftRng::from_rng(rng).map(|result| SmallRng(result))
}
}
@@ -955,7 +983,7 @@
#[deprecated(since="0.5.0", note="removed in favor of SmallRng")]
#[cfg(feature="std")]
pub fn weak_rng() -> XorShiftRng {
- XorShiftRng::from_rng(&mut thread_rng()).unwrap_or_else(|err|
+ XorShiftRng::from_rng(thread_rng()).unwrap_or_else(|err|
panic!("weak_rng failed: {:?}", err))
}
@@ -1182,7 +1210,7 @@
let mut rng1 = StdRng::from_seed(seed);
assert_eq!(rng1.next_u64(), 15759097995037006553);
- let mut rng2 = StdRng::from_rng(&mut rng1).unwrap();
+ let mut rng2 = StdRng::from_rng(rng1).unwrap();
assert_eq!(rng2.next_u64(), 6766915756997287454);
}
}
diff --git a/src/prng/chacha.rs b/src/prng/chacha.rs
index 30e70d4..91aa5da 100644
--- a/src/prng/chacha.rs
+++ b/src/prng/chacha.rs
@@ -94,8 +94,8 @@
ChaChaRng(BlockRng::<ChaChaCore>::from_seed(seed))
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
- BlockRng::<ChaChaCore>::from_rng(rng).map(|rng| ChaChaRng(rng))
+ fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
+ BlockRng::<ChaChaCore>::from_rng(rng).map(|result| ChaChaRng(result))
}
}
@@ -273,6 +273,7 @@
impl SeedableRng for ChaChaCore {
type Seed = [u8; SEED_WORDS*4];
+
fn from_seed(seed: Self::Seed) -> Self {
let mut seed_le = [0u32; SEED_WORDS];
le::read_u32_into(&seed, &mut seed_le);
@@ -302,7 +303,7 @@
let mut rng1 = ChaChaRng::from_seed(seed);
assert_eq!(rng1.next_u32(), 137206642);
- let mut rng2 = ChaChaRng::from_rng(&mut rng1).unwrap();
+ let mut rng2 = ChaChaRng::from_rng(rng1).unwrap();
assert_eq!(rng2.next_u32(), 1325750369);
}
diff --git a/src/prng/hc128.rs b/src/prng/hc128.rs
index 61c608e..137d240 100644
--- a/src/prng/hc128.rs
+++ b/src/prng/hc128.rs
@@ -91,8 +91,8 @@
Hc128Rng(BlockRng::<Hc128Core>::from_seed(seed))
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
- BlockRng::<Hc128Core>::from_rng(rng).map(|rng| Hc128Rng(rng))
+ fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
+ BlockRng::<Hc128Core>::from_rng(rng).map(|result| Hc128Rng(result))
}
}
diff --git a/src/prng/isaac.rs b/src/prng/isaac.rs
index d8f2e11..543d324 100644
--- a/src/prng/isaac.rs
+++ b/src/prng/isaac.rs
@@ -349,7 +349,7 @@
init(seed_extended, 2)
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
+ fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
// as the entire state.
let mut seed = [w(0u32); RAND_SIZE];
@@ -380,7 +380,7 @@
let mut rng1 = IsaacRng::from_seed(seed);
assert_eq!(rng1.next_u32(), 2869442790);
- let mut rng2 = IsaacRng::from_rng(&mut rng1).unwrap();
+ let mut rng2 = IsaacRng::from_rng(rng1).unwrap();
assert_eq!(rng2.next_u32(), 3094074039);
}
diff --git a/src/prng/isaac64.rs b/src/prng/isaac64.rs
index 27aba17..4a16213 100644
--- a/src/prng/isaac64.rs
+++ b/src/prng/isaac64.rs
@@ -325,7 +325,7 @@
init(seed_extended, 2)
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
+ fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
// Custom `from_rng` implementation that fills a seed with the same size
// as the entire state.
let mut seed = [w(0u64); RAND_SIZE];
@@ -356,7 +356,7 @@
let mut rng1 = Isaac64Rng::from_seed(seed);
assert_eq!(rng1.next_u64(), 14964555543728284049);
- let mut rng2 = Isaac64Rng::from_rng(&mut rng1).unwrap();
+ let mut rng2 = Isaac64Rng::from_rng(rng1).unwrap();
assert_eq!(rng2.next_u64(), 919595328260451758);
}
diff --git a/src/prng/xorshift.rs b/src/prng/xorshift.rs
index 87f4d50..b98a5cb 100644
--- a/src/prng/xorshift.rs
+++ b/src/prng/xorshift.rs
@@ -105,7 +105,7 @@
}
}
- fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
+ fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
let mut seed_u32 = [0u32; 4];
loop {
unsafe {
@@ -138,7 +138,7 @@
let mut rng1 = XorShiftRng::from_seed(seed);
assert_eq!(rng1.next_u64(), 4325440999699518727);
- let _rng2 = XorShiftRng::from_rng(&mut rng1).unwrap();
+ let _rng2 = XorShiftRng::from_rng(rng1).unwrap();
// Note: we cannot test the state of _rng2 because from_rng does not
// fix Endianness. This is allowed in the trait specification.
}
diff --git a/src/seq.rs b/src/seq.rs
index 6149ba3..4b20de4 100644
--- a/src/seq.rs
+++ b/src/seq.rs
@@ -41,7 +41,7 @@
/// ```
pub fn sample_iter<T, I, R>(rng: &mut R, iterable: I, amount: usize) -> Result<Vec<T>, Vec<T>>
where I: IntoIterator<Item=T>,
- R: Rng,
+ R: Rng + ?Sized,
{
let mut iter = iterable.into_iter();
let mut reservoir = Vec::with_capacity(amount);
@@ -85,7 +85,7 @@
/// println!("{:?}", seq::sample_slice(&mut rng, &values, 3));
/// ```
pub fn sample_slice<R, T>(rng: &mut R, slice: &[T], amount: usize) -> Vec<T>
- where R: Rng,
+ where R: Rng + ?Sized,
T: Clone
{
let indices = sample_indices(rng, slice.len(), amount);
@@ -113,7 +113,7 @@
/// println!("{:?}", seq::sample_slice_ref(&mut rng, &values, 3));
/// ```
pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T>
- where R: Rng
+ where R: Rng + ?Sized
{
let indices = sample_indices(rng, slice.len(), amount);
@@ -133,7 +133,7 @@
///
/// Panics if `amount > length`
pub fn sample_indices<R>(rng: &mut R, length: usize, amount: usize) -> Vec<usize>
- where R: Rng,
+ where R: Rng + ?Sized,
{
if amount > length {
panic!("`amount` must be less than or equal to `slice.len()`");
@@ -166,7 +166,7 @@
/// This is better than using a HashMap "cache" when `amount >= length / 2` since it does not
/// require allocating an extra cache and is much faster.
fn sample_indices_inplace<R>(rng: &mut R, length: usize, amount: usize) -> Vec<usize>
- where R: Rng,
+ where R: Rng + ?Sized,
{
debug_assert!(amount <= length);
let mut indices: Vec<usize> = Vec::with_capacity(length);
@@ -193,7 +193,7 @@
length: usize,
amount: usize,
) -> Vec<usize>
- where R: Rng,
+ where R: Rng + ?Sized,
{
debug_assert!(amount <= length);
#[cfg(feature="std")] let mut cache = HashMap::with_capacity(amount);