Skip to content

Commit e4b5219

Browse files
committed
Auto merge of rust-lang#146621 - cammeresi:peek-20250915, r=Amanieu
Make `PeekMut` generic over the allocator - plumb in allocator generic - additional testing Related: rust-lang#122742
2 parents ec38671 + 934ee04 commit e4b5219

File tree

3 files changed

+51
-44
lines changed

3 files changed

+51
-44
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -760,33 +760,6 @@ impl<T> Vec<T> {
760760
unsafe { Self::from_parts_in(ptr, length, capacity, Global) }
761761
}
762762

763-
/// Returns a mutable reference to the last item in the vector, or
764-
/// `None` if it is empty.
765-
///
766-
/// # Examples
767-
///
768-
/// Basic usage:
769-
///
770-
/// ```
771-
/// #![feature(vec_peek_mut)]
772-
/// let mut vec = Vec::new();
773-
/// assert!(vec.peek_mut().is_none());
774-
///
775-
/// vec.push(1);
776-
/// vec.push(5);
777-
/// vec.push(2);
778-
/// assert_eq!(vec.last(), Some(&2));
779-
/// if let Some(mut val) = vec.peek_mut() {
780-
/// *val = 0;
781-
/// }
782-
/// assert_eq!(vec.last(), Some(&0));
783-
/// ```
784-
#[inline]
785-
#[unstable(feature = "vec_peek_mut", issue = "122742")]
786-
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
787-
PeekMut::new(self)
788-
}
789-
790763
/// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity)`.
791764
///
792765
/// Returns the raw pointer to the underlying data, the length of
@@ -2747,6 +2720,33 @@ impl<T, A: Allocator> Vec<T, A> {
27472720
if predicate(last) { self.pop() } else { None }
27482721
}
27492722

2723+
/// Returns a mutable reference to the last item in the vector, or
2724+
/// `None` if it is empty.
2725+
///
2726+
/// # Examples
2727+
///
2728+
/// Basic usage:
2729+
///
2730+
/// ```
2731+
/// #![feature(vec_peek_mut)]
2732+
/// let mut vec = Vec::new();
2733+
/// assert!(vec.peek_mut().is_none());
2734+
///
2735+
/// vec.push(1);
2736+
/// vec.push(5);
2737+
/// vec.push(2);
2738+
/// assert_eq!(vec.last(), Some(&2));
2739+
/// if let Some(mut val) = vec.peek_mut() {
2740+
/// *val = 0;
2741+
/// }
2742+
/// assert_eq!(vec.last(), Some(&0));
2743+
/// ```
2744+
#[inline]
2745+
#[unstable(feature = "vec_peek_mut", issue = "122742")]
2746+
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T, A>> {
2747+
PeekMut::new(self)
2748+
}
2749+
27502750
/// Moves all the elements of `other` into `self`, leaving `other` empty.
27512751
///
27522752
/// # Panics

library/alloc/src/vec/peek_mut.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core::ops::{Deref, DerefMut};
22

33
use super::Vec;
4+
use crate::alloc::{Allocator, Global};
45
use crate::fmt;
56

67
/// Structure wrapping a mutable reference to the last item in a
@@ -11,19 +12,23 @@ use crate::fmt;
1112
///
1213
/// [`peek_mut`]: Vec::peek_mut
1314
#[unstable(feature = "vec_peek_mut", issue = "122742")]
14-
pub struct PeekMut<'a, T> {
15-
vec: &'a mut Vec<T>,
15+
pub struct PeekMut<
16+
'a,
17+
T,
18+
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
19+
> {
20+
vec: &'a mut Vec<T, A>,
1621
}
1722

1823
#[unstable(feature = "vec_peek_mut", issue = "122742")]
19-
impl<T: fmt::Debug> fmt::Debug for PeekMut<'_, T> {
24+
impl<T: fmt::Debug, A: Allocator> fmt::Debug for PeekMut<'_, T, A> {
2025
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2126
f.debug_tuple("PeekMut").field(self.deref()).finish()
2227
}
2328
}
2429

25-
impl<'a, T> PeekMut<'a, T> {
26-
pub(crate) fn new(vec: &'a mut Vec<T>) -> Option<Self> {
30+
impl<'a, T, A: Allocator> PeekMut<'a, T, A> {
31+
pub(super) fn new(vec: &'a mut Vec<T, A>) -> Option<Self> {
2732
if vec.is_empty() { None } else { Some(Self { vec }) }
2833
}
2934

@@ -36,17 +41,18 @@ impl<'a, T> PeekMut<'a, T> {
3641
}
3742

3843
#[unstable(feature = "vec_peek_mut", issue = "122742")]
39-
impl<'a, T> Deref for PeekMut<'a, T> {
44+
impl<'a, T, A: Allocator> Deref for PeekMut<'a, T, A> {
4045
type Target = T;
4146

4247
fn deref(&self) -> &Self::Target {
48+
let idx = self.vec.len() - 1;
4349
// SAFETY: PeekMut is only constructed if the vec is non-empty
44-
unsafe { self.vec.get_unchecked(self.vec.len() - 1) }
50+
unsafe { self.vec.get_unchecked(idx) }
4551
}
4652
}
4753

4854
#[unstable(feature = "vec_peek_mut", issue = "122742")]
49-
impl<'a, T> DerefMut for PeekMut<'a, T> {
55+
impl<'a, T, A: Allocator> DerefMut for PeekMut<'a, T, A> {
5056
fn deref_mut(&mut self) -> &mut Self::Target {
5157
let idx = self.vec.len() - 1;
5258
// SAFETY: PeekMut is only constructed if the vec is non-empty

library/alloctests/tests/vec.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,15 +2643,16 @@ fn test_peek_mut() {
26432643
assert!(vec.peek_mut().is_none());
26442644
vec.push(1);
26452645
vec.push(2);
2646-
if let Some(mut p) = vec.peek_mut() {
2647-
assert_eq!(*p, 2);
2648-
*p = 0;
2649-
assert_eq!(*p, 0);
2650-
PeekMut::pop(p);
2651-
assert_eq!(vec.len(), 1);
2652-
} else {
2653-
unreachable!()
2654-
}
2646+
let mut p = vec.peek_mut().unwrap();
2647+
assert_eq!(*p, 2);
2648+
*p = 0;
2649+
assert_eq!(*p, 0);
2650+
drop(p);
2651+
assert_eq!(vec, vec![1, 0]);
2652+
let p = vec.peek_mut().unwrap();
2653+
let p = PeekMut::pop(p);
2654+
assert_eq!(p, 0);
2655+
assert_eq!(vec, vec![1]);
26552656
}
26562657

26572658
/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments

0 commit comments

Comments
 (0)