Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump MSRV to 1.36 #1011

Merged
merged 17 commits into from Aug 28, 2020
5 changes: 2 additions & 3 deletions .travis.yml
Expand Up @@ -6,9 +6,8 @@ sudo: false

matrix:
include:
- rust: 1.32.0
name: "Linux, 1.32.0"
env: ALLOC=0
- rust: 1.36.0
name: "Linux, 1.36.0"
os: linux

- rust: stable
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -13,13 +13,15 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.
- impl PartialEq+Eq for StdRng, SmallRng, and StepRng (#975)
- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974)
- Document types supported by `random` (#994)
- Implement weighted sampling without replacement (#976, #1013)

### Changes
- `gen_range(a, b)` was replaced with `gen_range(a..b)`, and `gen_range(a..=b)`
is supported (#744, #1003). Note that `a` and `b` can no longer be references or SIMD types.
- Replace `AsByteSliceMut` with `Fill` (#940)
- Move alias method for `WeightedIndex` to `rand_distr` (#945)
- `Alphanumeric` samples bytes instead of chars (#935)
- The minimum supported Rust version is now 1.36 (#1011)
- Better NaN handling for `WeightedIndex` (#1005)
- Implement `IntoIterator` for `IndexVec`, replacing the `into_iter` method (#1007)
- Reduce packaged crate size (#983)
Expand Down
14 changes: 6 additions & 8 deletions README.md
Expand Up @@ -6,7 +6,7 @@
[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand)
[![API](https://docs.rs/rand/badge.svg)](https://docs.rs/rand)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

A Rust library for random number generation.

Expand Down Expand Up @@ -75,11 +75,11 @@ issue tracker with the keyword `yank` *should* uncover the motivation.

### Rust version requirements

Since version 0.7, Rand requires **Rustc version 1.32 or greater**.
Rand 0.5 requires Rustc 1.22 or greater while versions
0.4 and 0.3 (since approx. June 2017) require Rustc version 1.15 or
greater. Subsets of the Rand code may work with older Rust versions, but this
is not supported.
Since version 0.8, Rand requires **Rustc version 1.36 or greater**.
Rand 0.7 requires Rustc 1.32 or greater while versions 0.5 require Rustc 1.22 or
greater, and 0.4 and 0.3 (since approx. June 2017) require Rustc version 1.15 or
greater. Subsets of the Rand code may work with older Rust versions, but this is
not supported.

Travis CI always has a build with a pinned version of Rustc matching the oldest
supported Rust release. The current policy is that this can be updated in any
Expand All @@ -91,8 +91,6 @@ Rand is built with these features enabled by default:

- `std` enables functionality dependent on the `std` lib
- `alloc` (implied by `std`) enables functionality requiring an allocator
(when using this feature in `no_std`, Rand requires Rustc version 1.36 or
greater)
- `getrandom` (implied by `std`) is an optional dependency providing the code
behind `rngs::OsRng`
- `std_rng` enables inclusion of `StdRng`, `thread_rng` and `random`
Expand Down
2 changes: 1 addition & 1 deletion rand_chacha/README.md
Expand Up @@ -6,7 +6,7 @@
[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_chacha)
[![API](https://docs.rs/rand_chacha/badge.svg)](https://docs.rs/rand_chacha)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

A cryptographically secure random number generator that uses the ChaCha
algorithm.
Expand Down
2 changes: 1 addition & 1 deletion rand_core/README.md
Expand Up @@ -6,7 +6,7 @@
[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_core)
[![API](https://docs.rs/rand_core/badge.svg)](https://docs.rs/rand_core)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

Core traits and error types of the [rand] library, plus tools for implementing
RNGs.
Expand Down
2 changes: 2 additions & 0 deletions rand_core/src/error.rs
Expand Up @@ -11,6 +11,8 @@
use core::fmt;
use core::num::NonZeroU32;

#[cfg(feature = "std")] use std::boxed::Box;

/// Error type of random number generators
///
/// In order to be compatible with `std` and `no_std`, this type has two
Expand Down
87 changes: 57 additions & 30 deletions rand_core/src/impls.rs
Expand Up @@ -19,9 +19,6 @@

use crate::RngCore;
use core::cmp::min;
use core::mem::size_of;
use core::ptr::copy_nonoverlapping;
use core::slice;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
Expand Down Expand Up @@ -55,39 +52,30 @@ pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
}
}

macro_rules! impl_uint_from_fill {
($rng:expr, $ty:ty, $N:expr) => {{
debug_assert!($N == size_of::<$ty>());

let mut int: $ty = 0;
unsafe {
let ptr = &mut int as *mut $ty as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, $N);
$rng.fill_bytes(slice);
}
int
}};
}

macro_rules! fill_via_chunks {
($src:expr, $dst:expr, $ty:ty, $size:expr) => {{
let chunk_size_u8 = min($src.len() * $size, $dst.len());
let chunk_size = (chunk_size_u8 + $size - 1) / $size;
($src:expr, $dst:expr, $ty:ty) => {{
const SIZE: usize = core::mem::size_of::<$ty>();
let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;

// The following can be replaced with safe code, but unfortunately it's
// ca. 8% slower.
if cfg!(target_endian = "little") {
unsafe {
copy_nonoverlapping(
core::ptr::copy_nonoverlapping(
$src.as_ptr() as *const u8,
$dst.as_mut_ptr(),
chunk_size_u8);
}
} else {
for (&n, chunk) in $src.iter().zip($dst.chunks_mut($size)) {
for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
let tmp = n.to_le();
let src_ptr = &tmp as *const $ty as *const u8;
unsafe {
copy_nonoverlapping(src_ptr,
chunk.as_mut_ptr(),
chunk.len());
core::ptr::copy_nonoverlapping(
src_ptr,
chunk.as_mut_ptr(),
chunk.len());
}
}
}
Expand Down Expand Up @@ -127,7 +115,7 @@ macro_rules! fill_via_chunks {
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
fill_via_chunks!(src, dest, u32, 4)
fill_via_chunks!(src, dest, u32)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
Expand All @@ -141,17 +129,56 @@ pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
fill_via_chunks!(src, dest, u64, 8)
fill_via_chunks!(src, dest, u64)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
impl_uint_from_fill!(rng, u32, 4)
let mut buf = [0; 4];
rng.fill_bytes(&mut buf);
u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
impl_uint_from_fill!(rng, u64, 8)
let mut buf = [0; 8];
rng.fill_bytes(&mut buf);
u64::from_ne_bytes(buf)
}
vks marked this conversation as resolved.
Show resolved Hide resolved

// TODO: implement tests for the above
#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_fill_via_u32_chunks() {
let src = [1, 2, 3];
let mut dst = [0u8; 11];
assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

let mut dst = [0u8; 13];
assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

let mut dst = [0u8; 5];
assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
assert_eq!(dst, [1, 0, 0, 0, 2]);
}

#[test]
fn test_fill_via_u64_chunks() {
let src = [1, 2];
let mut dst = [0u8; 11];
assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

let mut dst = [0u8; 17];
assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

let mut dst = [0u8; 5];
assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
assert_eq!(dst, [1, 0, 0, 0, 0]);
}
}
30 changes: 9 additions & 21 deletions rand_core/src/le.rs
Expand Up @@ -11,36 +11,24 @@
//! Little-Endian order has been chosen for internal usage; this makes some
//! useful functions available.

use core::ptr;

macro_rules! read_slice {
($src:expr, $dst:expr, $size:expr, $which:ident) => {{
assert_eq!($src.len(), $size * $dst.len());

unsafe {
ptr::copy_nonoverlapping(
$src.as_ptr(),
$dst.as_mut_ptr() as *mut u8,
$src.len());
}
for v in $dst.iter_mut() {
*v = v.$which();
}
}};
}
use core::convert::TryInto;

/// Reads unsigned 32 bit integers from `src` into `dst`.
/// Borrowed from the `byteorder` crate.
#[inline]
pub fn read_u32_into(src: &[u8], dst: &mut [u32]) {
read_slice!(src, dst, 4, to_le);
assert!(4 * src.len() >= dst.len());
for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(4)) {
*out = u32::from_le_bytes(chunk.try_into().unwrap());
}
}

/// Reads unsigned 64 bit integers from `src` into `dst`.
/// Borrowed from the `byteorder` crate.
#[inline]
pub fn read_u64_into(src: &[u8], dst: &mut [u64]) {
read_slice!(src, dst, 8, to_le);
assert!(8 * src.len() >= dst.len());
for (out, chunk) in dst.iter_mut().zip(src.chunks_exact(8)) {
*out = u64::from_le_bytes(chunk.try_into().unwrap());
}
}

#[test]
Expand Down
7 changes: 4 additions & 3 deletions rand_core/src/lib.rs
Expand Up @@ -36,14 +36,15 @@
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![allow(clippy::unreadable_literal)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![no_std]

use core::convert::AsMut;
use core::default::Default;

#[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc;
#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box;
#[cfg(feature = "std")] extern crate std;
#[cfg(feature = "alloc")] extern crate alloc;
#[cfg(feature = "alloc")] use alloc::boxed::Box;

pub use error::Error;
#[cfg(feature = "getrandom")] pub use os::OsRng;
Expand Down
2 changes: 1 addition & 1 deletion rand_distr/README.md
Expand Up @@ -6,7 +6,7 @@
[[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_distr)
[![API](https://docs.rs/rand_distr/badge.svg)](https://docs.rs/rand_distr)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

Implements a full suite of random number distributions sampling routines.

Expand Down
5 changes: 1 addition & 4 deletions rand_distr/src/lib.rs
Expand Up @@ -72,14 +72,11 @@
//! - [`InverseGaussian`] distribution
//! - [`NormalInverseGaussian`] distribution

#[cfg(all(feature = "alloc", not(feature = "std")))]
#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;
// TODO: remove on MSRV bump to 1.36
#[cfg(feature = "std")]
extern crate std as alloc;

pub use rand::distributions::{
uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
Expand Down
2 changes: 1 addition & 1 deletion rand_hc/README.md
Expand Up @@ -6,7 +6,7 @@
[[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_hc)
[![API](https://docs.rs/rand_hc/badge.svg)](https://docs.rs/rand_hc)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

A cryptographically secure random number generator that uses the HC-128
algorithm.
Expand Down
2 changes: 1 addition & 1 deletion rand_pcg/README.md
Expand Up @@ -6,7 +6,7 @@
[![Book](https://img.shields.io/badge/book-master-yellow.svg)](https://rust-random.github.io/book/)
[![API](https://img.shields.io/badge/api-master-yellow.svg)](https://rust-random.github.io/rand/rand_pcg)
[![API](https://docs.rs/rand_pcg/badge.svg)](https://docs.rs/rand_pcg)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.32+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-random/rand#rust-version-requirements)

Implements a selection of PCG random number generators.

Expand Down
10 changes: 7 additions & 3 deletions src/distributions/mod.rs
Expand Up @@ -328,7 +328,7 @@ where
pub struct Standard;


#[cfg(all(test, feature = "std"))]
#[cfg(test)]
mod tests {
use super::{Distribution, Uniform};
use crate::Rng;
Expand All @@ -338,8 +338,12 @@ mod tests {
use crate::distributions::Open01;
let mut rng = crate::test::rng(210);
let distr = Open01;
let results: Vec<f32> = distr.sample_iter(&mut rng).take(100).collect();
println!("{:?}", results);
let mut iter = Distribution::<f32>::sample_iter(distr, &mut rng);
let mut sum: f32 = 0.;
for _ in 0..100 {
sum += iter.next().unwrap();
}
assert!(0. < sum && sum < 100.);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/other.rs
Expand Up @@ -206,7 +206,7 @@ where Standard: Distribution<T>
mod tests {
use super::*;
use crate::RngCore;
#[cfg(all(not(feature = "std"), feature = "alloc"))] use alloc::string::String;
#[cfg(feature = "alloc")] use alloc::string::String;

#[test]
fn test_misc() {
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/weighted.rs
Expand Up @@ -19,7 +19,7 @@ pub mod alias_method {
// This module exists to provide a deprecation warning which minimises
// compile errors, but still fails to compile if ever used.
use core::marker::PhantomData;
#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec;
use alloc::vec::Vec;
use super::WeightedError;

#[derive(Debug)]
Expand Down
4 changes: 2 additions & 2 deletions src/distributions/weighted_index.rs
Expand Up @@ -15,7 +15,7 @@ use core::cmp::PartialOrd;
use core::fmt;

// Note that this whole module is only imported if feature="alloc" is enabled.
#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec;
use alloc::vec::Vec;

#[cfg(feature = "serde1")]
use serde::{Serialize, Deserialize};
Expand Down Expand Up @@ -246,7 +246,7 @@ mod test {
#[cfg(feature = "serde1")]
#[test]
fn test_weightedindex_serde1() {
let weighted_index = WeightedIndex::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap();
let weighted_index = WeightedIndex::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap();

let ser_weighted_index = bincode::serialize(&weighted_index).unwrap();
let de_weighted_index: WeightedIndex<i32> =
Expand Down