Skip to content

Commit 26117e7

Browse files
committed
Make PRNGs implement Clone instead of Copy
Remove derivations of `Copy` trait from `ChaChaRng`, `IsaacRng`, `Isaac64Rng` and `StdRng` and implement the `Clone` trait instead. Copying is an implicit operation and the copy shares its internal state with the original generator. This means the the two generators will yield exactly the same sequence of values. This behaviour is considerably easy to trigger by, for example, passing the generator by value to a function. `Clone` trait, on the other hand, does no implicit copying. The user will only be able to either move the generator or ask for a copy explicitly, via the `clone` method. The only downside to this patch is the fact that the implementations of `Clone::clone` methods do not optimise down to a single memcpy, like the derived `Copy` implementations did. Although the `Copy` implementations of these random number generators are suspected to not be used much, this is a [breaking-change]. Fixes rust-lang#20170.
1 parent e64a819 commit 26117e7

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

src/librand/chacha.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of
2929
/// [1]: D. J. Bernstein, [*ChaCha, a variant of
3030
/// Salsa20*](http://cr.yp.to/chacha.html)
3131
32-
#[deriving(Copy)]
32+
#[allow(missing_copy_implementations)]
3333
pub struct ChaChaRng {
3434
buffer: [u32, ..STATE_WORDS], // Internal buffer of output
3535
state: [u32, ..STATE_WORDS], // Initial state
@@ -85,7 +85,7 @@ impl ChaChaRng {
8585
/// Create an ChaCha random number generator using the default
8686
/// fixed key of 8 zero words.
8787
pub fn new_unseeded() -> ChaChaRng {
88-
let mut rng = EMPTY;
88+
let mut rng = EMPTY.clone();
8989
rng.init(&[0, ..KEY_WORDS]);
9090
rng
9191
}
@@ -157,6 +157,16 @@ impl ChaChaRng {
157157
}
158158
}
159159

160+
impl Clone for ChaChaRng {
161+
fn clone(&self) -> ChaChaRng {
162+
ChaChaRng {
163+
buffer: self.buffer,
164+
state: self.state,
165+
index: self.index
166+
}
167+
}
168+
}
169+
160170
impl Rng for ChaChaRng {
161171
#[inline]
162172
fn next_u32(&mut self) -> u32 {
@@ -187,7 +197,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
187197
/// Only up to 8 words are used; if less than 8
188198
/// words are used, the remaining are set to zero.
189199
fn from_seed(seed: &'a [u32]) -> ChaChaRng {
190-
let mut rng = EMPTY;
200+
let mut rng = EMPTY.clone();
191201
rng.reseed(seed);
192202
rng
193203
}
@@ -203,7 +213,6 @@ impl Rand for ChaChaRng {
203213
}
204214
}
205215

206-
207216
#[cfg(test)]
208217
mod test {
209218
use std::prelude::*;

src/librand/isaac.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const RAND_SIZE_UINT: uint = 1 << (RAND_SIZE_LEN as uint);
2929
///
3030
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
3131
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
32-
#[deriving(Copy)]
32+
33+
#[allow(missing_copy_implementations)]
3334
pub struct IsaacRng {
3435
cnt: u32,
3536
rsl: [u32, ..RAND_SIZE_UINT],
@@ -51,7 +52,7 @@ impl IsaacRng {
5152
/// Create an ISAAC random number generator using the default
5253
/// fixed seed.
5354
pub fn new_unseeded() -> IsaacRng {
54-
let mut rng = EMPTY;
55+
let mut rng = EMPTY.clone();
5556
rng.init(false);
5657
rng
5758
}
@@ -179,6 +180,19 @@ impl IsaacRng {
179180
}
180181
}
181182

183+
impl Clone for IsaacRng {
184+
fn clone(&self) -> IsaacRng {
185+
IsaacRng {
186+
cnt: self.cnt,
187+
rsl: self.rsl,
188+
mem: self.mem,
189+
a: self.a,
190+
b: self.b,
191+
c: self.c
192+
}
193+
}
194+
}
195+
182196
impl Rng for IsaacRng {
183197
#[inline]
184198
fn next_u32(&mut self) -> u32 {
@@ -226,15 +240,15 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng {
226240
/// constructed with a given seed will generate the same sequence
227241
/// of values as all other generators constructed with that seed.
228242
fn from_seed(seed: &'a [u32]) -> IsaacRng {
229-
let mut rng = EMPTY;
243+
let mut rng = EMPTY.clone();
230244
rng.reseed(seed);
231245
rng
232246
}
233247
}
234248

235249
impl Rand for IsaacRng {
236250
fn rand<R: Rng>(other: &mut R) -> IsaacRng {
237-
let mut ret = EMPTY;
251+
let mut ret = EMPTY.clone();
238252
unsafe {
239253
let ptr = ret.rsl.as_mut_ptr() as *mut u8;
240254

@@ -264,7 +278,7 @@ const RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
264278
///
265279
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
266280
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
267-
#[deriving(Copy)]
281+
#[allow(missing_copy_implementations)]
268282
pub struct Isaac64Rng {
269283
cnt: uint,
270284
rsl: [u64, .. RAND_SIZE_64],
@@ -285,7 +299,7 @@ impl Isaac64Rng {
285299
/// Create a 64-bit ISAAC random number generator using the
286300
/// default fixed seed.
287301
pub fn new_unseeded() -> Isaac64Rng {
288-
let mut rng = EMPTY_64;
302+
let mut rng = EMPTY_64.clone();
289303
rng.init(false);
290304
rng
291305
}
@@ -415,6 +429,19 @@ impl Isaac64Rng {
415429
}
416430
}
417431

432+
impl Clone for Isaac64Rng {
433+
fn clone(&self) -> Isaac64Rng {
434+
Isaac64Rng {
435+
cnt: self.cnt,
436+
rsl: self.rsl,
437+
mem: self.mem,
438+
a: self.a,
439+
b: self.b,
440+
c: self.c
441+
}
442+
}
443+
}
444+
418445
impl Rng for Isaac64Rng {
419446
// FIXME #7771: having next_u32 like this should be unnecessary
420447
#[inline]
@@ -460,15 +487,15 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
460487
/// constructed with a given seed will generate the same sequence
461488
/// of values as all other generators constructed with that seed.
462489
fn from_seed(seed: &'a [u64]) -> Isaac64Rng {
463-
let mut rng = EMPTY_64;
490+
let mut rng = EMPTY_64.clone();
464491
rng.reseed(seed);
465492
rng
466493
}
467494
}
468495

469496
impl Rand for Isaac64Rng {
470497
fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
471-
let mut ret = EMPTY_64;
498+
let mut ret = EMPTY_64.clone();
472499
unsafe {
473500
let ptr = ret.rsl.as_mut_ptr() as *mut u8;
474501

src/libstd/rand/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ pub mod reader;
245245

246246
/// The standard RNG. This is designed to be efficient on the current
247247
/// platform.
248-
#[deriving(Copy)]
248+
#[allow(missing_copy_implementations)]
249+
#[deriving(Clone)]
249250
pub struct StdRng {
250251
rng: IsaacWordRng,
251252
}

0 commit comments

Comments
 (0)