Skip to content

Commit

Permalink
Relax Sized requirements for blanket impls (#1593)
Browse files Browse the repository at this point in the history
Relaxes `Sized` bound on blanket impls for `TryRngCore`, `TryCryptoRng`,
`UnwrapErr`, and `UnwrapMut`.
  • Loading branch information
fjarri authored Feb 20, 2025
1 parent ec6d5c0 commit 775b05b
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 4 deletions.
4 changes: 4 additions & 0 deletions rand_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### API changes
- Relax `Sized` bound on impls of `TryRngCore`, `TryCryptoRng` and `UnwrapMut` (#1593)

## [0.9.1] - 2025-02-16
### API changes
- Add `TryRngCore::unwrap_mut`, providing an impl of `RngCore` over `&mut rng` (#1589)
Expand Down
95 changes: 91 additions & 4 deletions rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub trait TryRngCore {
// Note that, unfortunately, this blanket impl prevents us from implementing
// `TryRngCore` for types which can be dereferenced to `TryRngCore`, i.e. `TryRngCore`
// will not be automatically implemented for `&mut R`, `Box<R>`, etc.
impl<R: RngCore> TryRngCore for R {
impl<R: RngCore + ?Sized> TryRngCore for R {
type Error = core::convert::Infallible;

#[inline]
Expand Down Expand Up @@ -290,7 +290,7 @@ impl<R: RngCore> TryRngCore for R {
/// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed.
pub trait TryCryptoRng: TryRngCore {}

impl<R: CryptoRng> TryCryptoRng for R {}
impl<R: CryptoRng + ?Sized> TryCryptoRng for R {}

/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`]
/// by panicking on potential errors.
Expand Down Expand Up @@ -321,7 +321,7 @@ impl<R: TryCryptoRng> CryptoRng for UnwrapErr<R> {}
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R);

impl<R: TryRngCore> RngCore for UnwrapMut<'_, R> {
impl<R: TryRngCore + ?Sized> RngCore for UnwrapMut<'_, R> {
#[inline]
fn next_u32(&mut self) -> u32 {
self.0.try_next_u32().unwrap()
Expand All @@ -338,7 +338,7 @@ impl<R: TryRngCore> RngCore for UnwrapMut<'_, R> {
}
}

impl<R: TryCryptoRng> CryptoRng for UnwrapMut<'_, R> {}
impl<R: TryCryptoRng + ?Sized> CryptoRng for UnwrapMut<'_, R> {}

/// A random number generator that can be explicitly seeded.
///
Expand Down Expand Up @@ -639,4 +639,91 @@ mod test {
// value-breakage test:
assert_eq!(results[0], 5029875928683246316);
}

// A stub RNG.
struct SomeRng;

impl RngCore for SomeRng {
fn next_u32(&mut self) -> u32 {
unimplemented!()
}
fn next_u64(&mut self) -> u64 {
unimplemented!()
}
fn fill_bytes(&mut self, _: &mut [u8]) {
unimplemented!()
}
}

impl CryptoRng for SomeRng {}

#[test]
fn dyn_rngcore_to_tryrngcore() {
// Illustrates the need for `+ ?Sized` bound in `impl<R: RngCore> TryRngCore for R`.

// A method in another crate taking a fallible RNG
fn third_party_api(_rng: &mut (impl TryRngCore + ?Sized)) -> bool {
true
}

// A method in our crate requiring an infallible RNG
fn my_api(rng: &mut dyn RngCore) -> bool {
// We want to call the method above
third_party_api(rng)
}

assert!(my_api(&mut SomeRng));
}

#[test]
fn dyn_cryptorng_to_trycryptorng() {
// Illustrates the need for `+ ?Sized` bound in `impl<R: CryptoRng> TryCryptoRng for R`.

// A method in another crate taking a fallible RNG
fn third_party_api(_rng: &mut (impl TryCryptoRng + ?Sized)) -> bool {
true
}

// A method in our crate requiring an infallible RNG
fn my_api(rng: &mut dyn CryptoRng) -> bool {
// We want to call the method above
third_party_api(rng)
}

assert!(my_api(&mut SomeRng));
}

#[test]
fn dyn_unwrap_mut_tryrngcore() {
// Illustrates the need for `+ ?Sized` bound in
// `impl<R: TryRngCore> RngCore for UnwrapMut<'_, R>`.

fn third_party_api(_rng: &mut impl RngCore) -> bool {
true
}

fn my_api(rng: &mut (impl TryRngCore + ?Sized)) -> bool {
let mut infallible_rng = rng.unwrap_mut();
third_party_api(&mut infallible_rng)
}

assert!(my_api(&mut SomeRng));
}

#[test]
fn dyn_unwrap_mut_trycryptorng() {
// Illustrates the need for `+ ?Sized` bound in
// `impl<R: TryCryptoRng> CryptoRng for UnwrapMut<'_, R>`.

fn third_party_api(_rng: &mut impl CryptoRng) -> bool {
true
}

fn my_api(rng: &mut (impl TryCryptoRng + ?Sized)) -> bool {
let mut infallible_rng = rng.unwrap_mut();
third_party_api(&mut infallible_rng)
}

assert!(my_api(&mut SomeRng));
}
}

0 comments on commit 775b05b

Please sign in to comment.