Skip to content

Commit db9ea5d

Browse files
committed
Add hash_table::UnsafeIter, iter() method to various iterators
1 parent bba4a01 commit db9ea5d

File tree

1 file changed

+182
-19
lines changed

1 file changed

+182
-19
lines changed

src/table.rs

Lines changed: 182 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::{fmt, iter::FusedIterator, marker::PhantomData};
1+
use core::{fmt, iter::FusedIterator, marker::PhantomData, ptr::NonNull};
22

33
use crate::{
44
control::Tag,
@@ -1071,6 +1071,35 @@ where
10711071
}
10721072
}
10731073

1074+
/// An iterator visiting all elements in arbitrary order,
1075+
/// with pointers to the elements.
1076+
/// The iterator element type is `NonNull<T>`.
1077+
///
1078+
/// This iterator is intended for APIs where only part of the elements are
1079+
/// mutable, with the remainder being immutable. In these cases, wrapping
1080+
/// the ordinary mutable iterator is incorrect because all components of
1081+
/// the element type will be [invariant]. A correct implementation will use
1082+
/// an appropriate [`PhantomData`] marker to make the immutable parts
1083+
/// [covariant] and the mutable parts invariant.
1084+
///
1085+
/// [invariant]: https://doc.rust-lang.org/stable/reference/subtyping.html#r-subtyping.variance.invariant
1086+
/// [covariant]: https://doc.rust-lang.org/stable/reference/subtyping.html#r-subtyping.variance.covariant
1087+
///
1088+
/// See the documentation for [`UnsafeIter`] for more information on how
1089+
/// to correctly use this.
1090+
///
1091+
/// # Safety
1092+
///
1093+
/// Any part of the returned elements which is mutated must be made invariant.
1094+
/// See the documentation for [`UnsafeIter`] for an example and further
1095+
/// explanation.
1096+
pub unsafe fn unsafe_iter(&mut self) -> UnsafeIter<'_, T> {
1097+
UnsafeIter {
1098+
inner: unsafe { self.raw.iter() },
1099+
marker: PhantomData,
1100+
}
1101+
}
1102+
10741103
/// An iterator producing the `usize` indices of all occupied buckets.
10751104
///
10761105
/// The order in which the iterator yields indices is unspecified
@@ -2508,6 +2537,16 @@ pub struct IterMut<'a, T> {
25082537
inner: RawIter<T>,
25092538
marker: PhantomData<&'a mut T>,
25102539
}
2540+
impl<'a, T> IterMut<'a, T> {
2541+
/// Returns a iterator of references over the remaining items.
2542+
#[cfg_attr(feature = "inline-more", inline)]
2543+
pub fn iter(&self) -> Iter<'_, T> {
2544+
Iter {
2545+
inner: self.inner.clone(),
2546+
marker: PhantomData,
2547+
}
2548+
}
2549+
}
25112550

25122551
impl<T> Default for IterMut<'_, T> {
25132552
#[cfg_attr(feature = "inline-more", inline)]
@@ -2556,12 +2595,123 @@ where
25562595
T: fmt::Debug,
25572596
{
25582597
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2559-
f.debug_list()
2560-
.entries(Iter {
2561-
inner: self.inner.clone(),
2562-
marker: PhantomData,
2563-
})
2564-
.finish()
2598+
f.debug_list().entries(self.iter()).finish()
2599+
}
2600+
}
2601+
2602+
/// An unsafe iterator over the entries of a `HashTable` in arbitrary order.
2603+
/// The iterator element type is `NonNull<T>`.
2604+
///
2605+
/// This `struct` is created by the [`unsafe_iter`] method on [`HashTable`].
2606+
///
2607+
/// This is used for implementations of iterators with "mixed" mutability on
2608+
/// the iterated elements. For example, a mutable iterator for a map may return
2609+
/// an immutable key alongside a mutable value, even though these are both
2610+
/// stored inside the table.
2611+
///
2612+
/// If you have no idea what any of this means, you probably should be using
2613+
/// [`IterMut`] instead, as it does not have any safety requirements.
2614+
///
2615+
/// # Safety
2616+
///
2617+
/// In order to correctly use this iterator, it should be wrapped in a safe
2618+
/// iterator struct with the appropriate [`PhantomData`] marker to indicate the
2619+
/// correct [variance].
2620+
///
2621+
/// For example, below is a simplified [`hash_map::IterMut`] implementation
2622+
/// that correctly returns a [covariant] key, and an [invariant] value:
2623+
///
2624+
/// [variance]: https://doc.rust-lang.org/stable/reference/subtyping.html#r-subtyping.variance
2625+
/// [covariant]: https://doc.rust-lang.org/stable/reference/subtyping.html#r-subtyping.variance.covariant
2626+
/// [invariant]: https://doc.rust-lang.org/stable/reference/subtyping.html#r-subtyping.variance.invariant
2627+
/// [`hash_map::IterMut`]: crate::hash_map::IterMut
2628+
///
2629+
/// ```rust
2630+
/// use core::marker::PhantomData;
2631+
/// use hashbrown::hash_table;
2632+
///
2633+
/// pub struct IterMut<'a, K, V> {
2634+
/// inner: hash_table::UnsafeIter<'a, (K, V)>,
2635+
/// // Covariant over keys, invariant over values
2636+
/// marker: PhantomData<(&'a K, &'a mut V)>,
2637+
/// }
2638+
/// impl<'a, K, V> Iterator for IterMut<'a, K, V> {
2639+
/// // Immutable keys, mutable values
2640+
/// type Item = (&'a K, &'a mut V);
2641+
///
2642+
/// fn next(&mut self) -> Option<Self::Item> {
2643+
/// // SAFETY: The lifetime of the dereferenced pointer is derived from
2644+
/// // the lifetime of its iterator, ensuring that it's always valid.
2645+
/// // Additionally, we match the mutability in `self.marker` to ensure
2646+
/// // the correct variance.
2647+
/// let (ref key, ref mut val) = unsafe { *self.inner.next() }?;
2648+
/// Some((key, val))
2649+
/// }
2650+
/// }
2651+
/// ```
2652+
pub struct UnsafeIter<'a, T> {
2653+
inner: RawIter<T>,
2654+
marker: PhantomData<&'a ()>,
2655+
}
2656+
impl<'a, T> UnsafeIter<'a, T> {
2657+
/// Returns a iterator of references over the remaining items.
2658+
#[cfg_attr(feature = "inline-more", inline)]
2659+
pub fn iter(&self) -> Iter<'_, T> {
2660+
Iter {
2661+
inner: self.inner.clone(),
2662+
marker: PhantomData,
2663+
}
2664+
}
2665+
}
2666+
2667+
impl<T> Default for UnsafeIter<'_, T> {
2668+
#[cfg_attr(feature = "inline-more", inline)]
2669+
fn default() -> Self {
2670+
UnsafeIter {
2671+
inner: Default::default(),
2672+
marker: PhantomData,
2673+
}
2674+
}
2675+
}
2676+
impl<'a, T> Iterator for UnsafeIter<'a, T> {
2677+
type Item = NonNull<T>;
2678+
2679+
fn next(&mut self) -> Option<Self::Item> {
2680+
// Avoid `Option::map` because it bloats LLVM IR.
2681+
match self.inner.next() {
2682+
Some(bucket) => Some(unsafe { NonNull::new_unchecked(bucket.as_ptr()) }),
2683+
None => None,
2684+
}
2685+
}
2686+
2687+
fn size_hint(&self) -> (usize, Option<usize>) {
2688+
self.inner.size_hint()
2689+
}
2690+
2691+
fn fold<B, F>(self, init: B, mut f: F) -> B
2692+
where
2693+
Self: Sized,
2694+
F: FnMut(B, Self::Item) -> B,
2695+
{
2696+
self.inner
2697+
.fold(init, |acc, bucket| unsafe { f(acc, NonNull::new_unchecked(bucket.as_ptr())) })
2698+
}
2699+
}
2700+
2701+
impl<T> ExactSizeIterator for UnsafeIter<'_, T> {
2702+
fn len(&self) -> usize {
2703+
self.inner.len()
2704+
}
2705+
}
2706+
2707+
impl<T> FusedIterator for UnsafeIter<'_, T> {}
2708+
2709+
impl<T> fmt::Debug for UnsafeIter<'_, T>
2710+
where
2711+
T: fmt::Debug,
2712+
{
2713+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2714+
f.debug_list().entries(self.iter()).finish()
25652715
}
25662716
}
25672717

@@ -2815,6 +2965,19 @@ where
28152965
{
28162966
inner: RawIntoIter<T, A>,
28172967
}
2968+
impl<T, A> IntoIter<T, A>
2969+
where
2970+
A: Allocator,
2971+
{
2972+
/// Returns a iterator of references over the remaining items.
2973+
#[cfg_attr(feature = "inline-more", inline)]
2974+
pub fn iter(&self) -> Iter<'_, T> {
2975+
Iter {
2976+
inner: self.inner.iter(),
2977+
marker: PhantomData,
2978+
}
2979+
}
2980+
}
28182981

28192982
impl<T, A: Allocator> Default for IntoIter<T, A> {
28202983
#[cfg_attr(feature = "inline-more", inline)]
@@ -2865,12 +3028,7 @@ where
28653028
A: Allocator,
28663029
{
28673030
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2868-
f.debug_list()
2869-
.entries(Iter {
2870-
inner: self.inner.iter(),
2871-
marker: PhantomData,
2872-
})
2873-
.finish()
3031+
f.debug_list().entries(self.iter()).finish()
28743032
}
28753033
}
28763034

@@ -2884,6 +3042,16 @@ where
28843042
pub struct Drain<'a, T, A: Allocator = Global> {
28853043
inner: RawDrain<'a, T, A>,
28863044
}
3045+
impl<'a, T, A: Allocator> Drain<'a, T, A> {
3046+
/// Returns a iterator of references over the remaining items.
3047+
#[cfg_attr(feature = "inline-more", inline)]
3048+
pub fn iter(&self) -> Iter<'_, T> {
3049+
Iter {
3050+
inner: self.inner.iter(),
3051+
marker: PhantomData,
3052+
}
3053+
}
3054+
}
28873055

28883056
impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
28893057
type Item = T;
@@ -2915,12 +3083,7 @@ impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
29153083

29163084
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
29173085
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2918-
f.debug_list()
2919-
.entries(Iter {
2920-
inner: self.inner.iter(),
2921-
marker: PhantomData,
2922-
})
2923-
.finish()
3086+
f.debug_list().entries(self.iter()).finish()
29243087
}
29253088
}
29263089

0 commit comments

Comments
 (0)