From e0eb2ee0fcc0b07afb901465f4a8ba7f07128f87 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 18 Feb 2025 12:03:52 -0800 Subject: [PATCH] rand_core: implement reborrow for `UnwrapMut` --- rand_core/CHANGELOG.md | 1 + rand_core/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index a9354a56f6..4d038133f4 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -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 diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 8092589d54..d41d0c0332 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -321,6 +321,21 @@ impl CryptoRng for UnwrapErr {} #[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 RngCore for UnwrapMut<'_, R> { #[inline] fn next_u32(&mut self) -> u32 { @@ -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 { + Ok(4) + } + fn try_next_u64(&mut self) -> Result { + 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); + } }