Skip to content

rand_core: implement reborrow for UnwrapMut #1595

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

Merged
merged 2 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion rand_core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl<R: BlockRngCore<Item = u32>> RngCore for BlockRng<R> {
fn next_u64(&mut self) -> u64 {
let read_u64 = |results: &[u32], index| {
let data = &results[index..=index + 1];
u64::from(data[1]) << 32 | u64::from(data[0])
(u64::from(data[1]) << 32) | u64::from(data[0])
};

let len = self.results.as_ref().len();
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);
}
}
2 changes: 1 addition & 1 deletion rand_pcg/src/pcg128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl SeedableRng for Mcg128Xsl64 {
// Read as if a little-endian u128 value:
let mut seed_u64 = [0u64; 2];
le::read_u64_into(&seed, &mut seed_u64);
let state = u128::from(seed_u64[0]) | u128::from(seed_u64[1]) << 64;
let state = u128::from(seed_u64[0]) | (u128::from(seed_u64[1]) << 64);
Mcg128Xsl64::new(state)
}
}
Expand Down