Skip to content

Commit

Permalink
rand_core: implement reborrow for UnwrapMut
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Feb 20, 2025
1 parent 975f602 commit e0eb2ee
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
1 change: 1 addition & 0 deletions rand_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### API changes
- Relax `Sized` bound on impls of `TryRngCore`, `TryCryptoRng` and `UnwrapMut` (#1593)
- Add `UnwrapMut::re` to reborrow the inner rng with a tighter lifetime (#1595)

## [0.9.1] - 2025-02-16
### API changes
Expand Down
42 changes: 42 additions & 0 deletions rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,21 @@ 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, R: TryRngCore + ?Sized> UnwrapMut<'r, R> {
/// Reborrow with a new lifetime
///
/// Rust allows references like `&T` or `&mut T` to be "reborrowed" through
/// coercion: essentially, the pointer is copied under a new, shorter, lifetime.
/// Until rfcs#1403 lands, reborrows on user types require a method call.
#[inline(always)]
pub fn re<'b>(&'b mut self) -> UnwrapMut<'b, R>
where
'r: 'b,
{
UnwrapMut(self.0)
}
}

impl<R: TryRngCore + ?Sized> RngCore for UnwrapMut<'_, R> {
#[inline]
fn next_u32(&mut self) -> u32 {
Expand Down Expand Up @@ -726,4 +741,31 @@ mod test {

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

#[test]
fn reborrow_unwrap_mut() {
struct FourRng;

impl TryRngCore for FourRng {
type Error = core::convert::Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(4)
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
unimplemented!()
}
fn try_fill_bytes(&mut self, _: &mut [u8]) -> Result<(), Self::Error> {
unimplemented!()
}
}

let mut rng = FourRng;
let mut rng = rng.unwrap_mut();

assert_eq!(rng.next_u32(), 4);
let mut rng2 = rng.re();
assert_eq!(rng2.next_u32(), 4);
drop(rng2);
assert_eq!(rng.next_u32(), 4);
}
}

0 comments on commit e0eb2ee

Please sign in to comment.