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
getrandom
features you are using. The following features are now available:"rdrand"
: Use the RDRAND instruction onno_std
x86/x86_64
targets."js"
: Use JavaScript calls onwasm32-unknown-unknown
. This replaces thestdweb
andwasm-bindgen
features, 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
custom
feature to provide a panicking implementation. - Windows XP and stdweb are, as of
getrandom
version 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
rdrand
feature 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::prelude::*; use rand::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 (
Uniform
types 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
Uniform
distribution now additionally supports thechar
type, so for examplerng.gen_range('a'..='f')
is now supported. UniformSampler::sample_single_inclusive
was added.- The
Alphanumeric
distribution 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 fromu8
tochar
. 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::{distributions::Alphanumeric, Rng}; fn main() { let mut rng = rand::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
WeightedIndex
employing the alias method was moved fromrand
torand_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::WeightedAliasIndex
was added (moved from therand
crate)rand_distr::InverseGaussian
andrand_distr::NormalInverseGaussian
were added- The
Geometric
andHypergeometric
distributions are now supported. - A different algorithm is used for the
Beta
distribution, improving both performance and accuracy. This is a value-breaking change. - The
Normal
andLogNormal
distributions now support afrom_mean_cv
constructor method andfrom_zscore
sampler method. rand_distr::Dirichlet
now uses boxed slices internally instead ofVec
. Therefore, the weights are taken as a slice instead of aVec
as input. For example, the followingrand_distr 0.2
code
can be replaced with the followinguse rand_distr_0_2::Dirichlet; Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
rand_distr 0.3
code:use rand_distr::Dirichlet; Dirichlet::new(&[1.0, 2.0, 3.0]).unwrap();
rand_distr::Poisson
does no longer support samplingu64
values directly. Old code may have to be updated to perform the conversion fromf64
explicitly.- The custom
Float
trait inrand_distr
was replaced withnum_traits::Float
. Any implementations ofFloat
for user-defined types have to be migrated. Thanks to the math functions fromnum_traits::Float
,rand_distr
now supportsno_std
.
Additionally, there were some minor improvements:
- The treatment of rounding errors and NaN was improved for the
WeightedIndex
distribution. - The
rand_distr::Exp
distribution now supports thelambda = 0
parametrization.
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).