From 40bfeeef156961ad92d35be3a848f28e8be99e4c Mon Sep 17 00:00:00 2001 From: Ankit-cs Date: Fri, 9 Oct 2026 22:15:21 +0530 Subject: [PATCH 1/2] refactor: standardize lifetimes to 'valid (#735) Replaces custom lifetimes (e.g., 'slice, 'data, 'cell) in benches, fuzz targets, and tests with the standard 'valid lifetime to ensure codebase consistency as per maintainer feedback. --- benches/bench.rs | 3 ++- fuzz/fuzz_targets/main.rs | 12 +++++++----- tests/main.rs | 8 +++++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index 5c979aa8..282c9f6c 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -15,7 +15,8 @@ use { const VEC_SIZE: usize = 16; const SPILLED_SIZE: usize = 100; -trait Vector: for<'a> From<&'a [T]> + Extend + FromIterator { +/// A trait defining common vector operations, implemented by vectors taking items from a slice of lifetime 'valid. +trait Vector: for<'valid> From<&'valid [T]> + Extend + FromIterator { fn new() -> Self; fn push(&mut self, val: T); fn pop(&mut self) -> Option; diff --git a/fuzz/fuzz_targets/main.rs b/fuzz/fuzz_targets/main.rs index 71fb83c9..4701577c 100644 --- a/fuzz/fuzz_targets/main.rs +++ b/fuzz/fuzz_targets/main.rs @@ -18,18 +18,20 @@ const MAX_CAP: usize = 1024; pub struct Bounded(pub T); // Bounded `usize` between `0..=CAP` -impl<'a, const CAP: usize> Arbitrary<'a> for Bounded { +impl<'valid, const CAP: usize> Arbitrary<'valid> for Bounded { + /// Generates an arbitrary bounded usize value using the unstructured fuzzing data of lifetime 'valid. #[inline] - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + fn arbitrary(u: &mut arbitrary::Unstructured<'valid>) -> arbitrary::Result { Ok(Bounded(u.int_in_range(0..=CAP)?)) } } // Bounded `Vec` whose length is between `0..=CAP` -impl<'a, T, const CAP: usize> Arbitrary<'a> for Bounded, CAP> -where T: Arbitrary<'a> +impl<'valid, T, const CAP: usize> Arbitrary<'valid> for Bounded, CAP> +where T: Arbitrary<'valid> { - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + /// Generates an arbitrary bounded vector by consuming items from the unstructured data stream of lifetime 'valid. + fn arbitrary(u: &mut arbitrary::Unstructured<'valid>) -> arbitrary::Result { let len = u.int_in_range(0..=CAP)?; let vec = u .arbitrary_iter()? diff --git a/tests/main.rs b/tests/main.rs index 22ecfb9f..9e0b4bff 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -237,7 +237,8 @@ fn splice_inline_fill_then_move_tail_ub_test() { #[test] fn splice_reserve_panic() { - struct CountDrop<'a>(&'a Cell); + /// A helper struct that increments a counter when dropped, bound to the cell's lifetime 'valid. + struct CountDrop<'valid>(&'valid Cell); impl Drop for CountDrop<'_> { fn drop(&mut self) { @@ -311,9 +312,10 @@ fn into_iter_rev() { #[test] fn into_iter_drop() { - struct DropCounter<'a>(&'a Cell); + /// A helper struct that increments a counter when dropped, bound to the cell's lifetime 'valid. + struct DropCounter<'valid>(&'valid Cell); - impl<'a> Drop for DropCounter<'a> { + impl<'valid> Drop for DropCounter<'valid> { fn drop(&mut self) { self.0.set(self.0.get() + 1); } From 35414d3c1a0aad6c437c2613d287977932b240a3 Mon Sep 17 00:00:00 2001 From: Ankit-cs Date: Sat, 10 Oct 2026 09:32:17 +0530 Subject: [PATCH 2/2] refactor: address reviewer feedback (remove doc comments, fix lifetime collisions) --- benches/bench.rs | 1 - fuzz/fuzz_targets/main.rs | 2 -- src/iterators/drain.rs | 24 ++++++++++---------- src/iterators/extractif.rs | 4 ++-- src/iterators/rayon.rs | 10 ++++----- src/iterators/splice.rs | 15 ++++++++----- src/lib.rs | 45 +++++++++++++++++++------------------- src/specialization.rs | 10 ++++----- tests/main.rs | 2 -- 9 files changed, 57 insertions(+), 56 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index 282c9f6c..2d11e03e 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -15,7 +15,6 @@ use { const VEC_SIZE: usize = 16; const SPILLED_SIZE: usize = 100; -/// A trait defining common vector operations, implemented by vectors taking items from a slice of lifetime 'valid. trait Vector: for<'valid> From<&'valid [T]> + Extend + FromIterator { fn new() -> Self; fn push(&mut self, val: T); diff --git a/fuzz/fuzz_targets/main.rs b/fuzz/fuzz_targets/main.rs index 4701577c..a8565278 100644 --- a/fuzz/fuzz_targets/main.rs +++ b/fuzz/fuzz_targets/main.rs @@ -19,7 +19,6 @@ pub struct Bounded(pub T); // Bounded `usize` between `0..=CAP` impl<'valid, const CAP: usize> Arbitrary<'valid> for Bounded { - /// Generates an arbitrary bounded usize value using the unstructured fuzzing data of lifetime 'valid. #[inline] fn arbitrary(u: &mut arbitrary::Unstructured<'valid>) -> arbitrary::Result { Ok(Bounded(u.int_in_range(0..=CAP)?)) @@ -30,7 +29,6 @@ impl<'valid, const CAP: usize> Arbitrary<'valid> for Bounded { impl<'valid, T, const CAP: usize> Arbitrary<'valid> for Bounded, CAP> where T: Arbitrary<'valid> { - /// Generates an arbitrary bounded vector by consuming items from the unstructured data stream of lifetime 'valid. fn arbitrary(u: &mut arbitrary::Unstructured<'valid>) -> arbitrary::Result { let len = u.int_in_range(0..=CAP)?; let vec = u diff --git a/src/iterators/drain.rs b/src/iterators/drain.rs index edf77343..655caf16 100644 --- a/src/iterators/drain.rs +++ b/src/iterators/drain.rs @@ -11,7 +11,7 @@ use crate::{ /// Returned from [`SmallVec::drain`][1]. /// /// [1]: struct.SmallVec.html#method.drain -pub struct Drain<'a, Item: 'a, const INLINE: usize, Heap: Allocator = Global> { +pub struct Drain<'valid, Item: 'valid, const INLINE: usize, Heap: Allocator = Global> { // `vec` points to a valid object within its lifetime. // This is ensured by the fact that we're holding an iterator to its items. // @@ -21,12 +21,12 @@ pub struct Drain<'a, Item: 'a, const INLINE: usize, Heap: Allocator = Global> { // even though vec has length < tail_start pub(crate) tail_start: usize, pub(crate) tail_len: usize, - pub(crate) iter: core::slice::Iter<'a, Item>, + pub(crate) iter: core::slice::Iter<'valid, Item>, pub(crate) vec: core::ptr::NonNull> } -impl<'a, Item: 'a, const INLINE: usize, Heap: Allocator> Iterator - for Drain<'a, Item, INLINE, Heap> +impl<'valid, Item: 'valid, const INLINE: usize, Heap: Allocator> Iterator + for Drain<'valid, Item, INLINE, Heap> { type Item = Item; @@ -45,8 +45,8 @@ impl<'a, Item: 'a, const INLINE: usize, Heap: Allocator> Iterator } } -impl<'a, Item: 'a, const INLINE: usize, Heap: Allocator> DoubleEndedIterator - for Drain<'a, Item, INLINE, Heap> +impl<'valid, Item: 'valid, const INLINE: usize, Heap: Allocator> DoubleEndedIterator + for Drain<'valid, Item, INLINE, Heap> { #[inline] fn next_back(&mut self) -> Option { @@ -71,15 +71,17 @@ impl core::iter::FusedIterator { } -impl<'a, Item: 'a, const INLINE: usize, Heap: Allocator> Drop for Drain<'a, Item, INLINE, Heap> { +impl<'valid, Item: 'valid, const INLINE: usize, Heap: Allocator> Drop + for Drain<'valid, Item, INLINE, Heap> +{ fn drop(&mut self) { /// Moves back the un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, Item, const INLINE: usize, Heap: Allocator>( - &'r mut Drain<'a, Item, INLINE, Heap> + struct DropGuard<'guard, 'valid, Item, const INLINE: usize, Heap: Allocator>( + &'guard mut Drain<'valid, Item, INLINE, Heap> ); - impl<'r, 'a, Item, const INLINE: usize, Heap: Allocator> Drop - for DropGuard<'r, 'a, Item, INLINE, Heap> + impl<'guard, 'valid, Item, const INLINE: usize, Heap: Allocator> Drop + for DropGuard<'guard, 'valid, Item, INLINE, Heap> { fn drop(&mut self) { if self.0.tail_len > 0 { diff --git a/src/iterators/extractif.rs b/src/iterators/extractif.rs index f53b8f65..a539592b 100644 --- a/src/iterators/extractif.rs +++ b/src/iterators/extractif.rs @@ -10,10 +10,10 @@ use crate::{ /// Returned from [`SmallVec::extract_if`][1]. /// /// [1]: struct.SmallVec.html#method.extract_if -pub struct ExtractIf<'a, Item, const INLINE: usize, F, Heap: Allocator = Global> +pub struct ExtractIf<'valid, Item, const INLINE: usize, F, Heap: Allocator = Global> where F: FnMut(&mut Item) -> bool { - pub(crate) vec: &'a mut SmallVec, + pub(crate) vec: &'valid mut SmallVec, /// The index of the item that will be inspected by the next call to `next`. pub(crate) idx: usize, /// Elements at and beyond this point will be retained. Must be equal or diff --git a/src/iterators/rayon.rs b/src/iterators/rayon.rs index c567b292..efb24d0f 100644 --- a/src/iterators/rayon.rs +++ b/src/iterators/rayon.rs @@ -24,7 +24,7 @@ use { } }; -struct SliceDrain<'a, Item>(slice::IterMut<'a, Item>); +struct SliceDrain<'valid, Item>(slice::IterMut<'valid, Item>); impl Iterator for SliceDrain<'_, Item> { type Item = Item; @@ -52,13 +52,13 @@ impl Drop for SliceDrain<'_, Item> { } } -struct DrainProducer<'a, Item>(&'a mut [Item]); +struct DrainProducer<'valid, Item>(&'valid mut [Item]); -impl<'a, Item: Send> Producer for DrainProducer<'a, Item> { - type IntoIter = SliceDrain<'a, Item>; +impl<'valid, Item: Send> Producer for DrainProducer<'valid, Item> { + type IntoIter = SliceDrain<'valid, Item>; type Item = Item; - fn into_iter(mut self) -> SliceDrain<'a, Item> { + fn into_iter(mut self) -> SliceDrain<'valid, Item> { SliceDrain(take(&mut self.0).iter_mut()) } diff --git a/src/iterators/splice.rs b/src/iterators/splice.rs index bee64a74..7d50a3d1 100644 --- a/src/iterators/splice.rs +++ b/src/iterators/splice.rs @@ -8,13 +8,15 @@ use super::{ drain::Drain }; -pub struct Splice<'a, I: Iterator + 'a, const INLINE: usize, Heap: Allocator = Global> { - drain: Drain<'a, I::Item, INLINE, Heap>, +pub struct Splice<'valid, I: Iterator + 'valid, const INLINE: usize, Heap: Allocator = Global> { + drain: Drain<'valid, I::Item, INLINE, Heap>, replace_with: I } -impl<'a, I: Iterator + 'a, const INLINE: usize, Heap: Allocator> Splice<'a, I, INLINE, Heap> { - pub(crate) fn new(drain: Drain<'a, I::Item, INLINE, Heap>, replace_with: I) -> Self { +impl<'valid, I: Iterator + 'valid, const INLINE: usize, Heap: Allocator> + Splice<'valid, I, INLINE, Heap> +{ + pub(crate) fn new(drain: Drain<'valid, I::Item, INLINE, Heap>, replace_with: I) -> Self { Self { drain, replace_with @@ -22,9 +24,10 @@ impl<'a, I: Iterator + 'a, const INLINE: usize, Heap: Allocator> Splice<'a, I, I } } -impl<'a, I, const INLINE: usize, Heap: Allocator> core::fmt::Debug for Splice<'a, I, INLINE, Heap> +impl<'valid, I, const INLINE: usize, Heap: Allocator> core::fmt::Debug + for Splice<'valid, I, INLINE, Heap> where - I: core::fmt::Debug + Iterator + 'a, + I: core::fmt::Debug + Iterator + 'valid, ::Item: core::fmt::Debug { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/src/lib.rs b/src/lib.rs index dc890e01..a1e4bae5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -326,7 +326,7 @@ impl SmallVec { /// // Overwrite memory with [4, 5, 6]. /// // /// // This is only safe if `spilled` is true! Otherwise, we are - /// // writing into the old `SmallVec`'s inline storage on the + /// // writing into the old `SmallVec`'valid inline storage on the /// // stack. /// assert!(spilled); /// for i in 0..length { @@ -1057,8 +1057,8 @@ impl SmallVec { // panicked. It shifts unchecked elements to cover holes and // `set_len` to the correct length. In cases when predicate and // `drop` never panic, it will be optimized out. - struct Guard<'a, Item, const INLINE: usize, Heap: Allocator> { - v: &'a mut SmallVec, + struct Guard<'valid, Item, const INLINE: usize, Heap: Allocator> { + v: &'valid mut SmallVec, read: usize, write: usize, original_len: usize @@ -1193,7 +1193,7 @@ impl SmallVec { } } - pub fn leak<'a>(self) -> &'a mut [Item] { + pub fn leak<'valid>(self) -> &'valid mut [Item] { let (length, on_heap) = self.length.parts(); if !on_heap { panic!( @@ -1473,11 +1473,11 @@ impl Drop for DropGuard { } } -struct DropDealloc<'a, Heap: Allocator> { +struct DropDealloc<'valid, Heap: Allocator> { ptr: NonNull, size_bytes: usize, align: usize, - allocator: &'a Heap + allocator: &'valid Heap } impl Drop for DropDealloc<'_, Heap> { @@ -1761,14 +1761,14 @@ impl Extend for SmallVec Extend<&'a Item> +impl<'valid, Item: Clone + 'valid, const INLINE: usize, Heap: Allocator> Extend<&'valid Item> for SmallVec { #[inline] - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { #[cfg(feature = "specialization")] { - specialization::SpecExtend::<&'a Item, _>::spec_extend(self, iter.into_iter()); + specialization::SpecExtend::<&'valid Item, _>::spec_extend(self, iter.into_iter()); } #[cfg(not(feature = "specialization"))] @@ -1793,22 +1793,22 @@ impl core::iter::FromIterator for SmallVec IntoIterator - for &'a SmallVec +impl<'valid, Item, const INLINE: usize, Heap: Allocator> IntoIterator + for &'valid SmallVec { - type IntoIter = core::slice::Iter<'a, Item>; - type Item = &'a Item; + type IntoIter = core::slice::Iter<'valid, Item>; + type Item = &'valid Item; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'a, Item, const INLINE: usize, Heap: Allocator> IntoIterator - for &'a mut SmallVec +impl<'valid, Item, const INLINE: usize, Heap: Allocator> IntoIterator + for &'valid mut SmallVec { - type IntoIter = core::slice::IterMut<'a, Item>; - type Item = &'a mut Item; + type IntoIter = core::slice::IterMut<'valid, Item>; + type Item = &'valid mut Item; fn into_iter(self) -> Self::IntoIter { self.iter_mut() @@ -1836,7 +1836,7 @@ impl Zeroize for SmallVec Zeroize for SmallVec arbitrary::Arbitrary<'a> for SmallVec -where Item: arbitrary::Arbitrary<'a> +impl<'valid, Item, const INLINE: usize> arbitrary::Arbitrary<'valid> + for SmallVec +where Item: arbitrary::Arbitrary<'valid> { - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + fn arbitrary(u: &mut arbitrary::Unstructured<'valid>) -> arbitrary::Result { u.arbitrary_iter()?.collect() } - fn arbitrary_take_rest(u: arbitrary::Unstructured<'a>) -> arbitrary::Result { + fn arbitrary_take_rest(u: arbitrary::Unstructured<'valid>) -> arbitrary::Result { u.arbitrary_take_rest_iter()?.collect() } diff --git a/src/specialization.rs b/src/specialization.rs index 24115347..ced0487f 100644 --- a/src/specialization.rs +++ b/src/specialization.rs @@ -136,10 +136,10 @@ impl } } -impl<'a, Item: 'a, const INLINE: usize, I, Heap: Allocator> SpecExtend<&'a Item, I> +impl<'valid, Item: 'valid, const INLINE: usize, I, Heap: Allocator> SpecExtend<&'valid Item, I> for SmallVec where - I: Iterator, + I: Iterator, Item: Clone { #[inline] @@ -148,11 +148,11 @@ where } } -impl<'a, Item: 'a, const INLINE: usize, Heap: Allocator> - SpecExtend<&'a Item, core::slice::Iter<'a, Item>> for SmallVec +impl<'valid, Item: 'valid, const INLINE: usize, Heap: Allocator> + SpecExtend<&'valid Item, core::slice::Iter<'valid, Item>> for SmallVec where Item: Copy { - fn spec_extend(&mut self, iter: core::slice::Iter<'a, Item>) { + fn spec_extend(&mut self, iter: core::slice::Iter<'valid, Item>) { let slice = iter.as_slice(); let length = slice.len(); let old_len = self.len(); diff --git a/tests/main.rs b/tests/main.rs index 9e0b4bff..35c3b12a 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -237,7 +237,6 @@ fn splice_inline_fill_then_move_tail_ub_test() { #[test] fn splice_reserve_panic() { - /// A helper struct that increments a counter when dropped, bound to the cell's lifetime 'valid. struct CountDrop<'valid>(&'valid Cell); impl Drop for CountDrop<'_> { @@ -312,7 +311,6 @@ fn into_iter_rev() { #[test] fn into_iter_drop() { - /// A helper struct that increments a counter when dropped, bound to the cell's lifetime 'valid. struct DropCounter<'valid>(&'valid Cell); impl<'valid> Drop for DropCounter<'valid> {