Updating to 0.8
In the following, instructions are provided for porting your code from
rand 0.7 and rand_distr 0.2 to rand 0.8 and rand_distr 0.3.
Dependencies
Rand crates now require rustc version 1.36.0 or later.
This allowed us to remove some unsafe code and simplify the internal cfg logic.
The dependency on getrandom was bumped to version 0.2. While this does not
affect Rand's API, you may be affected by some of the breaking changes even if
you use getrandom only as a dependency:
- You may have to update the
getrandomfeatures you are using. The following features are now available:"rdrand": Use the RDRAND instruction onno_stdx86/x86_64targets."js": Use JavaScript calls onwasm32-unknown-unknown. This replaces thestdwebandwasm-bindgenfeatures, which are removed."custom": Allows you to specify a custom implementation.
- Unsupported targets no longer compile. If you require the previous behavior
(panicking at runtime instead of failing to compile), you can use the
customfeature to provide a panicking implementation. - Windows XP and stdweb are, as of
getrandomversion 0.2.1, no longer supported. If you require support for either of these platforms you may add a dependency ongetrandom = "=0.2.0"to pin this version. - Hermit, L4Re and UEFI are no longer officially supported. You can use the
rdrandfeature on these platforms. - The minimum supported Linux kernel version is now 2.6.32.
If you are using getrandom's API directly, there are further breaking changes
that may affect you. See its
changelog.
Serde has been re-added as an optional dependency (use the serde1 feature
flag), supporting many types (where appropriate). StdRng and SmallRng are
deliberately excluded since these types are not portable.
Core features
ThreadRng
ThreadRng no longer implements Copy. This was necessary to fix a possible
use-after-free in its thread-local destructor. Any code relying on ThreadRng
being copied must be updated to use a mutable reference instead. For example,
use rand_0_7::distributions::{Distribution, Standard};
let rng = rand_0_7::thread_rng();
let a: u32 = Standard.sample_iter(rng).next().unwrap();
let b: u32 = Standard.sample_iter(rng).next().unwrap();
can be replaced with the following code:
extern crate rand; use rand_0_8::prelude::*; use rand_0_8::distributions::Standard; fn main () { let mut rng = thread_rng(); let a: u32 = Standard.sample_iter(&mut rng).next().unwrap(); let b: u32 = Standard.sample_iter(&mut rng).next().unwrap(); }
gen_range
Rng::gen_range now takes a Range instead of two numbers. Thus, replace
gen_range(a, b) with gen_range(a..b). We suggest using the following regular
expression to search-replace in all files:
- replace
gen_range\(([^,]*),\s*([^)]*)\) - with
gen_range(\1..\2) - or with
gen_range($1..$2)(if your tool does not support backreferences)
Most IDEs support search-replace-across-files or similar; alternatively an external tool such as Regexxer may be used.
This change has a couple of other implications:
- inclusive ranges are now supported, e.g.
gen_range(1..=6)orgen_range('A'..='Z') - it may be necessary to explicitly dereference some parameters
- SIMD types are no longer supported (
Uniformtypes may still be used directly)
fill
The AsByteSliceMut trait was replaced with the Fill trait. This should
only affect code implementing AsByteSliceMut on user-defined types, since the
Rng::fill and Rng::try_fill retain support for previously-supported types.
Fill supports some additional slice types which could not be supported with
AsByteSliceMut: [bool], [char], [f32], [f64].
adapter
The entire rand::rngs::adapter module is now restricted to the std feature.
While this is technically a breaking change, it should only affect no_std code
using ReseedingRng, which is unlikely to exist in the wild.
Generators
StdRng has switched from the 20-round ChaCha20 to ChaCha12 for improved
performance. This is a reduction in complexity but the 12-round variant is still
considered secure: see rand#932. This is a value-breaking change for StdRng.
SmallRng now uses the Xoshiro128++ and Xoshiro256++ algorithm on 32-bit and 64-bit platforms respectively. This reduces correlations of random data generated from similar seeds and improves performance. It is a value-breaking change.
We now implement PartialEq and Eq for StdRng, SmallRng, and StepRng.
Distributions
Several smaller changes occurred to rand distributions:
- The
Uniformdistribution now additionally supports thechartype, so for examplerng.gen_range('a'..='f')is now supported. UniformSampler::sample_single_inclusivewas added.- The
Alphanumericdistribution now samples bytes instead of chars. This more closely reflects the internally used type, but old code likely has to be adapted to perform the conversion fromu8tochar. For example, with Rand 0.7 you could write:
With Rand 0.8, this is equivalent to the following:use rand_0_7::{distributions::Alphanumeric, Rng}; let mut rng = rand_0_7::thread_rng(); let chars: String = std::iter::repeat(()) .map(|()| rng.sample(Alphanumeric)) .take(7) .collect();extern crate rand; use rand_0_8::{distributions::Alphanumeric, Rng}; fn main() { let mut rng = rand_0_8::thread_rng(); let chars: String = std::iter::repeat(()) .map(|()| rng.sample(Alphanumeric)) .map(char::from) .take(7) .collect(); println!("chars = \"{chars}\""); } - The alternative implementation of
WeightedIndexemploying the alias method was moved fromrandtorand_distr::weighted_alias::WeightedAliasIndex. The alias method is faster for large sizes, but it suffers from a slow initialization, making it less generally useful.
In rand_distr v0.4, more changes occurred (since v0.2):
rand_distr::weighted_alias::WeightedAliasIndexwas added (moved from therandcrate)rand_distr::InverseGaussianandrand_distr::NormalInverseGaussianwere added- The
GeometricandHypergeometricdistributions are now supported. - A different algorithm is used for the
Betadistribution, improving both performance and accuracy. This is a value-breaking change. - The
NormalandLogNormaldistributions now support afrom_mean_cvconstructor method andfrom_zscoresampler method. rand_distr::Dirichletnow uses boxed slices internally instead ofVec. Therefore, the weights are taken as a slice instead of aVecas input. For example, the followingrand_distr 0.2code
can be replaced with the followinguse rand_distr_0_2::Dirichlet; Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();rand_distr 0.3code:use rand_distr_0_4::Dirichlet; Dirichlet::new(&[1.0, 2.0, 3.0]).unwrap();rand_distr::Poissondoes no longer support samplingu64values directly. Old code may have to be updated to perform the conversion fromf64explicitly.- The custom
Floattrait inrand_distrwas replaced withnum_traits::Float. Any implementations ofFloatfor user-defined types have to be migrated. Thanks to the math functions fromnum_traits::Float,rand_distrnow supportsno_std.
Additionally, there were some minor improvements:
- The treatment of rounding errors and NaN was improved for the
WeightedIndexdistribution. - The
rand_distr::Expdistribution now supports thelambda = 0parametrization.
Sequences
Weighted sampling without replacement is now supported, see
rand::seq::index::sample_weighted and
SliceRandom::choose_multiple_weighted.
There have been value-breaking
changes to
IteratorRandom::choose, improving accuracy and performance. Furthermore,
IteratorRandom::choose_stable was added to provide an alternative that
sacrifices performance for independence of iterator size hints.
Feature flags
StdRng is now gated behind a new feature flag, std_rng. This is enabled by
default.
The nightly feature no longer implies the simd_support feature. If you were
relying on this for SIMD support, you will have to use simd_support feature
directly.
Tests
Value-stability tests were added for all distributions (rand#786), helping enforce our rules regarding value-breaking changes (see Reproducibility section).