diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index 18f2f6a0b72..a9354a56f65 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -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) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 0336c5bc2a4..8092589d544 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -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`, etc. -impl TryRngCore for R { +impl TryRngCore for R { type Error = core::convert::Infallible; #[inline] @@ -290,7 +290,7 @@ impl TryRngCore for R { /// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed. pub trait TryCryptoRng: TryRngCore {} -impl TryCryptoRng for R {} +impl TryCryptoRng for R {} /// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`] /// by panicking on potential errors. @@ -321,7 +321,7 @@ impl CryptoRng for UnwrapErr {} #[derive(Debug, Eq, PartialEq, Hash)] pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R); -impl RngCore for UnwrapMut<'_, R> { +impl RngCore for UnwrapMut<'_, R> { #[inline] fn next_u32(&mut self) -> u32 { self.0.try_next_u32().unwrap() @@ -338,7 +338,7 @@ impl RngCore for UnwrapMut<'_, R> { } } -impl CryptoRng for UnwrapMut<'_, R> {} +impl CryptoRng for UnwrapMut<'_, R> {} /// A random number generator that can be explicitly seeded. /// @@ -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 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 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 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 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)); + } }