Skip to content

Commit ee1d96f

Browse files
authored
rand_core: implement reborrow for UnwrapMut (#1595)
2 parents 775b05b + e0eb2ee commit ee1d96f

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

rand_core/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## Unreleased
88
### API changes
99
- Relax `Sized` bound on impls of `TryRngCore`, `TryCryptoRng` and `UnwrapMut` (#1593)
10+
- Add `UnwrapMut::re` to reborrow the inner rng with a tighter lifetime (#1595)
1011

1112
## [0.9.1] - 2025-02-16
1213
### API changes

rand_core/src/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<R: BlockRngCore<Item = u32>> RngCore for BlockRng<R> {
197197
fn next_u64(&mut self) -> u64 {
198198
let read_u64 = |results: &[u32], index| {
199199
let data = &results[index..=index + 1];
200-
u64::from(data[1]) << 32 | u64::from(data[0])
200+
(u64::from(data[1]) << 32) | u64::from(data[0])
201201
};
202202

203203
let len = self.results.as_ref().len();

rand_core/src/lib.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,21 @@ impl<R: TryCryptoRng> CryptoRng for UnwrapErr<R> {}
321321
#[derive(Debug, Eq, PartialEq, Hash)]
322322
pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R);
323323

324+
impl<'r, R: TryRngCore + ?Sized> UnwrapMut<'r, R> {
325+
/// Reborrow with a new lifetime
326+
///
327+
/// Rust allows references like `&T` or `&mut T` to be "reborrowed" through
328+
/// coercion: essentially, the pointer is copied under a new, shorter, lifetime.
329+
/// Until rfcs#1403 lands, reborrows on user types require a method call.
330+
#[inline(always)]
331+
pub fn re<'b>(&'b mut self) -> UnwrapMut<'b, R>
332+
where
333+
'r: 'b,
334+
{
335+
UnwrapMut(self.0)
336+
}
337+
}
338+
324339
impl<R: TryRngCore + ?Sized> RngCore for UnwrapMut<'_, R> {
325340
#[inline]
326341
fn next_u32(&mut self) -> u32 {
@@ -726,4 +741,31 @@ mod test {
726741

727742
assert!(my_api(&mut SomeRng));
728743
}
744+
745+
#[test]
746+
fn reborrow_unwrap_mut() {
747+
struct FourRng;
748+
749+
impl TryRngCore for FourRng {
750+
type Error = core::convert::Infallible;
751+
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
752+
Ok(4)
753+
}
754+
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
755+
unimplemented!()
756+
}
757+
fn try_fill_bytes(&mut self, _: &mut [u8]) -> Result<(), Self::Error> {
758+
unimplemented!()
759+
}
760+
}
761+
762+
let mut rng = FourRng;
763+
let mut rng = rng.unwrap_mut();
764+
765+
assert_eq!(rng.next_u32(), 4);
766+
let mut rng2 = rng.re();
767+
assert_eq!(rng2.next_u32(), 4);
768+
drop(rng2);
769+
assert_eq!(rng.next_u32(), 4);
770+
}
729771
}

rand_pcg/src/pcg128.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl SeedableRng for Mcg128Xsl64 {
234234
// Read as if a little-endian u128 value:
235235
let mut seed_u64 = [0u64; 2];
236236
le::read_u64_into(&seed, &mut seed_u64);
237-
let state = u128::from(seed_u64[0]) | u128::from(seed_u64[1]) << 64;
237+
let state = u128::from(seed_u64[0]) | (u128::from(seed_u64[1]) << 64);
238238
Mcg128Xsl64::new(state)
239239
}
240240
}

0 commit comments

Comments
 (0)