Skip to content

Commit 57163f6

Browse files
authored
Merge pull request #319 from dhardy/generics
Generics
2 parents fc757b3 + e5d2480 commit 57163f6

File tree

11 files changed

+68
-39
lines changed

11 files changed

+68
-39
lines changed

benches/misc.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn misc_gen_bool_var(b: &mut Bencher) {
3838

3939
#[bench]
4040
fn misc_shuffle_100(b: &mut Bencher) {
41-
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
41+
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
4242
let x : &mut [usize] = &mut [1; 100];
4343
b.iter(|| {
4444
rng.shuffle(x);
@@ -48,7 +48,7 @@ fn misc_shuffle_100(b: &mut Bencher) {
4848

4949
#[bench]
5050
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
51-
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
51+
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
5252
let x : &[usize] = &[1; 100];
5353
b.iter(|| {
5454
black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e));
@@ -57,7 +57,7 @@ fn misc_sample_iter_10_of_100(b: &mut Bencher) {
5757

5858
#[bench]
5959
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
60-
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
60+
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
6161
let x : &[usize] = &[1; 100];
6262
b.iter(|| {
6363
black_box(sample_slice(&mut rng, x, 10));
@@ -66,7 +66,7 @@ fn misc_sample_slice_10_of_100(b: &mut Bencher) {
6666

6767
#[bench]
6868
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
69-
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
69+
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
7070
let x : &[usize] = &[1; 100];
7171
b.iter(|| {
7272
black_box(sample_slice_ref(&mut rng, x, 10));
@@ -77,7 +77,7 @@ macro_rules! sample_indices {
7777
($name:ident, $amount:expr, $length:expr) => {
7878
#[bench]
7979
fn $name(b: &mut Bencher) {
80-
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
80+
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
8181
b.iter(|| {
8282
black_box(sample_indices(&mut rng, $length, $amount));
8383
})

rand-core/src/impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
323323
}
324324
}
325325

326-
fn from_rng<RNG: RngCore>(rng: &mut RNG) -> Result<Self, Error> {
326+
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
327327
let results_empty = R::Results::default();
328328
Ok(Self {
329329
core: R::from_rng(rng)?,

rand-core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ pub trait SeedableRng: Sized {
317317
/// [`NewRng`]: https://docs.rs/rand/0.5/rand/trait.NewRng.html
318318
/// [`OsRng`]: https://docs.rs/rand/0.5/rand/os/struct.OsRng.html
319319
/// [`XorShiftRng`]: https://docs.rs/rand/0.5/rand/prng/xorshift/struct.XorShiftRng.html
320-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
320+
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
321321
let mut seed = Self::Seed::default();
322322
rng.try_fill_bytes(seed.as_mut())?;
323323
Ok(Self::from_seed(seed))

src/distributions/other.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ mod tests {
165165

166166
#[test]
167167
fn test_misc() {
168-
let mut rng: &mut RngCore = &mut ::test::rng(820);
168+
let rng: &mut RngCore = &mut ::test::rng(820);
169169

170170
rng.sample::<char, _>(Uniform);
171171
rng.sample::<bool, _>(Uniform);

src/lib.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -332,16 +332,40 @@ pub trait Rand : Sized {
332332
/// An automatically-implemented extension trait on [`RngCore`] providing high-level
333333
/// generic methods for sampling values and other convenience methods.
334334
///
335-
/// This is the primary trait to use when generating random values. Example:
335+
/// This is the primary trait to use when generating random values.
336+
///
337+
/// # Generic usage
338+
///
339+
/// The basic pattern is `fn foo<R: Rng + ?Sized>(rng: &mut R)`. Some
340+
/// things are worth noting here:
341+
///
342+
/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no
343+
/// difference whether we use `R: Rng` or `R: RngCore`.
344+
/// - The `+ ?Sized` un-bounding allows functions to be called directly on
345+
/// type-erased references; i.e. `foo(r)` where `r: &mut RngCore`. Without
346+
/// this it would be necessary to write `foo(&mut r)`.
347+
///
348+
/// An alternative pattern is possible: `fn foo<R: Rng>(rng: R)`. This has some
349+
/// trade-offs. It allows the argument to be consumed directly without a `&mut`
350+
/// (which is how `from_rng(thread_rng())` works); also it still works directly
351+
/// on references (including type-erased references). Unfortunately within the
352+
/// function `foo` it is not known whether `rng` is a reference type or not,
353+
/// hence many uses of `rng` require an extra reference, either explicitly
354+
/// (`distr.sample(&mut rng)`) or implicitly (`rng.gen()`); one may hope the
355+
/// optimiser can remove redundant references later.
356+
///
357+
/// Example:
336358
///
337359
/// ```rust
338360
/// use rand::Rng;
339361
///
340-
/// fn use_rng<R: Rng + ?Sized>(rng: &mut R) -> f32 {
362+
/// fn foo<R: Rng + ?Sized>(rng: &mut R) -> f32 {
341363
/// rng.gen()
342364
/// }
343365
/// ```
344366
///
367+
/// # Iteration
368+
///
345369
/// Iteration over an `Rng` can be achieved using `iter::repeat` as follows:
346370
///
347371
/// ```rust
@@ -635,7 +659,7 @@ pub trait Rng: RngCore {
635659
}
636660
}
637661

638-
impl<R: RngCore> Rng for R {}
662+
impl<R: RngCore + ?Sized> Rng for R {}
639663

640664
/// Trait for casting types to byte slices
641665
///
@@ -800,7 +824,7 @@ pub trait NewRng: SeedableRng {
800824
///
801825
/// fn foo() -> Result<(), Error> {
802826
/// // This uses StdRng, but is valid for any R: SeedableRng
803-
/// let mut rng = StdRng::from_rng(&mut EntropyRng::new())?;
827+
/// let mut rng = StdRng::from_rng(EntropyRng::new())?;
804828
///
805829
/// println!("random number: {}", rng.gen_range(1, 10));
806830
/// Ok(())
@@ -812,7 +836,7 @@ pub trait NewRng: SeedableRng {
812836
#[cfg(feature="std")]
813837
impl<R: SeedableRng> NewRng for R {
814838
fn new() -> R {
815-
R::from_rng(&mut EntropyRng::new()).unwrap_or_else(|err|
839+
R::from_rng(EntropyRng::new()).unwrap_or_else(|err|
816840
panic!("NewRng::new() failed: {}", err))
817841
}
818842
}
@@ -860,8 +884,8 @@ impl SeedableRng for StdRng {
860884
StdRng(Hc128Rng::from_seed(seed))
861885
}
862886

863-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
864-
Hc128Rng::from_rng(rng).map(|rng| StdRng(rng))
887+
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
888+
Hc128Rng::from_rng(rng).map(|result| StdRng(result))
865889
}
866890
}
867891

@@ -896,14 +920,18 @@ impl CryptoRng for StdRng {}
896920
/// efficient:
897921
///
898922
/// ```
923+
/// use std::iter;
899924
/// use rand::{SeedableRng, SmallRng, thread_rng};
900925
///
901926
/// // Create a big, expensive to initialize and slower, but unpredictable RNG.
902927
/// // This is cached and done only once per thread.
903928
/// let mut thread_rng = thread_rng();
904-
/// // Create small, cheap to initialize and fast RNG with a random seed.
905-
/// // This is very unlikely to fail.
906-
/// let mut small_rng = SmallRng::from_rng(&mut thread_rng).unwrap();
929+
/// // Create small, cheap to initialize and fast RNGs with random seeds.
930+
/// // One can generally assume this won't fail.
931+
/// let rngs: Vec<SmallRng> = iter::repeat(())
932+
/// .map(|()| SmallRng::from_rng(&mut thread_rng).unwrap())
933+
/// .take(10)
934+
/// .collect();
907935
/// ```
908936
///
909937
/// [Xorshift]: struct.XorShiftRng.html
@@ -937,8 +965,8 @@ impl SeedableRng for SmallRng {
937965
SmallRng(XorShiftRng::from_seed(seed))
938966
}
939967

940-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
941-
XorShiftRng::from_rng(rng).map(|rng| SmallRng(rng))
968+
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
969+
XorShiftRng::from_rng(rng).map(|result| SmallRng(result))
942970
}
943971
}
944972

@@ -955,7 +983,7 @@ impl SeedableRng for SmallRng {
955983
#[deprecated(since="0.5.0", note="removed in favor of SmallRng")]
956984
#[cfg(feature="std")]
957985
pub fn weak_rng() -> XorShiftRng {
958-
XorShiftRng::from_rng(&mut thread_rng()).unwrap_or_else(|err|
986+
XorShiftRng::from_rng(thread_rng()).unwrap_or_else(|err|
959987
panic!("weak_rng failed: {:?}", err))
960988
}
961989

@@ -1182,7 +1210,7 @@ mod test {
11821210
let mut rng1 = StdRng::from_seed(seed);
11831211
assert_eq!(rng1.next_u64(), 15759097995037006553);
11841212

1185-
let mut rng2 = StdRng::from_rng(&mut rng1).unwrap();
1213+
let mut rng2 = StdRng::from_rng(rng1).unwrap();
11861214
assert_eq!(rng2.next_u64(), 6766915756997287454);
11871215
}
11881216
}

src/prng/chacha.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ impl SeedableRng for ChaChaRng {
9494
ChaChaRng(BlockRng::<ChaChaCore>::from_seed(seed))
9595
}
9696

97-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
98-
BlockRng::<ChaChaCore>::from_rng(rng).map(|rng| ChaChaRng(rng))
97+
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
98+
BlockRng::<ChaChaCore>::from_rng(rng).map(|result| ChaChaRng(result))
9999
}
100100
}
101101

@@ -273,6 +273,7 @@ impl ChaChaCore {
273273

274274
impl SeedableRng for ChaChaCore {
275275
type Seed = [u8; SEED_WORDS*4];
276+
276277
fn from_seed(seed: Self::Seed) -> Self {
277278
let mut seed_le = [0u32; SEED_WORDS];
278279
le::read_u32_into(&seed, &mut seed_le);
@@ -302,7 +303,7 @@ mod test {
302303
let mut rng1 = ChaChaRng::from_seed(seed);
303304
assert_eq!(rng1.next_u32(), 137206642);
304305

305-
let mut rng2 = ChaChaRng::from_rng(&mut rng1).unwrap();
306+
let mut rng2 = ChaChaRng::from_rng(rng1).unwrap();
306307
assert_eq!(rng2.next_u32(), 1325750369);
307308
}
308309

src/prng/hc128.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ impl SeedableRng for Hc128Rng {
9191
Hc128Rng(BlockRng::<Hc128Core>::from_seed(seed))
9292
}
9393

94-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
95-
BlockRng::<Hc128Core>::from_rng(rng).map(|rng| Hc128Rng(rng))
94+
fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
95+
BlockRng::<Hc128Core>::from_rng(rng).map(|result| Hc128Rng(result))
9696
}
9797
}
9898

src/prng/isaac.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl SeedableRng for IsaacRng {
349349
init(seed_extended, 2)
350350
}
351351

352-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
352+
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
353353
// Custom `from_rng` implementation that fills a seed with the same size
354354
// as the entire state.
355355
let mut seed = [w(0u32); RAND_SIZE];
@@ -380,7 +380,7 @@ mod test {
380380
let mut rng1 = IsaacRng::from_seed(seed);
381381
assert_eq!(rng1.next_u32(), 2869442790);
382382

383-
let mut rng2 = IsaacRng::from_rng(&mut rng1).unwrap();
383+
let mut rng2 = IsaacRng::from_rng(rng1).unwrap();
384384
assert_eq!(rng2.next_u32(), 3094074039);
385385
}
386386

src/prng/isaac64.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl SeedableRng for Isaac64Rng {
325325
init(seed_extended, 2)
326326
}
327327

328-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
328+
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
329329
// Custom `from_rng` implementation that fills a seed with the same size
330330
// as the entire state.
331331
let mut seed = [w(0u64); RAND_SIZE];
@@ -356,7 +356,7 @@ mod test {
356356
let mut rng1 = Isaac64Rng::from_seed(seed);
357357
assert_eq!(rng1.next_u64(), 14964555543728284049);
358358

359-
let mut rng2 = Isaac64Rng::from_rng(&mut rng1).unwrap();
359+
let mut rng2 = Isaac64Rng::from_rng(rng1).unwrap();
360360
assert_eq!(rng2.next_u64(), 919595328260451758);
361361
}
362362

src/prng/xorshift.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl SeedableRng for XorShiftRng {
105105
}
106106
}
107107

108-
fn from_rng<R: RngCore>(rng: &mut R) -> Result<Self, Error> {
108+
fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
109109
let mut seed_u32 = [0u32; 4];
110110
loop {
111111
unsafe {
@@ -138,7 +138,7 @@ mod tests {
138138
let mut rng1 = XorShiftRng::from_seed(seed);
139139
assert_eq!(rng1.next_u64(), 4325440999699518727);
140140

141-
let _rng2 = XorShiftRng::from_rng(&mut rng1).unwrap();
141+
let _rng2 = XorShiftRng::from_rng(rng1).unwrap();
142142
// Note: we cannot test the state of _rng2 because from_rng does not
143143
// fix Endianness. This is allowed in the trait specification.
144144
}

src/seq.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use super::Rng;
4141
/// ```
4242
pub fn sample_iter<T, I, R>(rng: &mut R, iterable: I, amount: usize) -> Result<Vec<T>, Vec<T>>
4343
where I: IntoIterator<Item=T>,
44-
R: Rng,
44+
R: Rng + ?Sized,
4545
{
4646
let mut iter = iterable.into_iter();
4747
let mut reservoir = Vec::with_capacity(amount);
@@ -85,7 +85,7 @@ pub fn sample_iter<T, I, R>(rng: &mut R, iterable: I, amount: usize) -> Result<V
8585
/// println!("{:?}", seq::sample_slice(&mut rng, &values, 3));
8686
/// ```
8787
pub fn sample_slice<R, T>(rng: &mut R, slice: &[T], amount: usize) -> Vec<T>
88-
where R: Rng,
88+
where R: Rng + ?Sized,
8989
T: Clone
9090
{
9191
let indices = sample_indices(rng, slice.len(), amount);
@@ -113,7 +113,7 @@ pub fn sample_slice<R, T>(rng: &mut R, slice: &[T], amount: usize) -> Vec<T>
113113
/// println!("{:?}", seq::sample_slice_ref(&mut rng, &values, 3));
114114
/// ```
115115
pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) -> Vec<&'a T>
116-
where R: Rng
116+
where R: Rng + ?Sized
117117
{
118118
let indices = sample_indices(rng, slice.len(), amount);
119119

@@ -133,7 +133,7 @@ pub fn sample_slice_ref<'a, R, T>(rng: &mut R, slice: &'a [T], amount: usize) ->
133133
///
134134
/// Panics if `amount > length`
135135
pub fn sample_indices<R>(rng: &mut R, length: usize, amount: usize) -> Vec<usize>
136-
where R: Rng,
136+
where R: Rng + ?Sized,
137137
{
138138
if amount > length {
139139
panic!("`amount` must be less than or equal to `slice.len()`");
@@ -166,7 +166,7 @@ pub fn sample_indices<R>(rng: &mut R, length: usize, amount: usize) -> Vec<usize
166166
/// This is better than using a HashMap "cache" when `amount >= length / 2` since it does not
167167
/// require allocating an extra cache and is much faster.
168168
fn sample_indices_inplace<R>(rng: &mut R, length: usize, amount: usize) -> Vec<usize>
169-
where R: Rng,
169+
where R: Rng + ?Sized,
170170
{
171171
debug_assert!(amount <= length);
172172
let mut indices: Vec<usize> = Vec::with_capacity(length);
@@ -193,7 +193,7 @@ fn sample_indices_cache<R>(
193193
length: usize,
194194
amount: usize,
195195
) -> Vec<usize>
196-
where R: Rng,
196+
where R: Rng + ?Sized,
197197
{
198198
debug_assert!(amount <= length);
199199
#[cfg(feature="std")] let mut cache = HashMap::with_capacity(amount);

0 commit comments

Comments
 (0)