From dca67d07f9d0f3e43cc826a3ee1ae8c797711cfa Mon Sep 17 00:00:00 2001 From: CHANDANA GOWDA Date: Wed, 14 Oct 2026 21:13:53 +0530 Subject: [PATCH 01/11] feat: restore may_dangle drop support --- Cargo.toml | 1 + src/lib.rs | 28 ++++++++++++++++++++++++++++ tests/may_dangle.rs | 15 +++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 tests/may_dangle.rs diff --git a/Cargo.toml b/Cargo.toml index 9cc0b6dc..42d7ec08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ strip = false allocator-api = [] allocator-api2 = ["dep:allocator-api2", "allocator-api"] internals = [] +may_dangle = [] proptest = ["dep:proptest", "std"] rayon = ["std", "dep:rayon"] serde = ["dep:serde_core"] diff --git a/src/lib.rs b/src/lib.rs index 22663609..539b4a81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(feature = "specialization", allow(incomplete_features))] #![cfg_attr(feature = "specialization", feature(specialization, trusted_len))] +#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))] #![cfg_attr( all(feature = "allocator-api", not(feature = "allocator-api2")), feature(allocator_api) @@ -1492,6 +1493,33 @@ impl Drop for DropDealloc<'_, Heap> { } } +#[cfg(feature = "may_dangle")] +unsafe impl<#[may_dangle] Item, const INLINE: usize, Heap: Allocator> Drop + for SmallVec +{ + fn drop(&mut self) { + let (length, on_heap) = self.length.parts(); + // SAFETY: the tag tells which member is active + let ptr = unsafe { self.raw.as_mut_ptr(on_heap) }; + // SAFETY: see above + unsafe { + let _drop_dealloc = if on_heap { + let capacity = self.raw.heap.1; + Some(DropDealloc { + ptr: NonNull::new_unchecked(ptr as *mut u8), + size_bytes: capacity * size_of::(), + align: align_of::(), + allocator: &self.allocator + }) + } else { + None + }; + core::ptr::slice_from_raw_parts_mut(ptr, length).drop_in_place(); + } + } +} + +#[cfg(not(feature = "may_dangle"))] impl Drop for SmallVec { fn drop(&mut self) { let (length, on_heap) = self.length.parts(); diff --git a/tests/may_dangle.rs b/tests/may_dangle.rs new file mode 100644 index 00000000..58b40146 --- /dev/null +++ b/tests/may_dangle.rs @@ -0,0 +1,15 @@ +#![cfg(feature = "may_dangle")] + +use smallvec::SmallVec; + +#[derive(Default)] +struct MyData<'a> { + arr: SmallVec<&'a u8, 5>, + dat: u8 +} + +#[test] +fn may_dangle_allows_borrow_of_another_field() { + let mut dat = MyData::default(); + dat.arr.push(&dat.dat); +} From 7dceb739cce3a0170364de0a9ff857e15ccb4afc Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 12:58:14 +0200 Subject: [PATCH 02/11] Fix typo in feature attribute for may-dangle Signed-off-by: Alejandro Vaz --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 257efa54..b16ea380 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(feature = "specialization", allow(incomplete_features))] #![cfg_attr(feature = "specialization", feature(specialization, trusted_len))] -#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))] +#![cfg_attr(feature = "may-dangle", feature(dropck_eyepatch))] #![cfg_attr( all(feature = "allocator-api", not(feature = "allocator-api2")), feature(allocator_api) From 0919a3d03750700ab265b90b780654c33c7e48d1 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 12:58:37 +0200 Subject: [PATCH 03/11] Rename feature 'may_dangle' to 'may-dangle' Signed-off-by: Alejandro Vaz --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index aab131a9..7b256fc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ strip = false allocator-api = [] allocator-api2 = ["allocator-api", "dep:allocator-api2"] internals = [] -may_dangle = [] +may-dangle = [] proptest = ["dep:proptest", "std"] rayon = ["dep:rayon", "std"] serde = ["dep:serde_core"] From 95528f673f501208d274861dc833a3adb91d47c1 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:03:07 +0200 Subject: [PATCH 04/11] Refactor Drop implementation for SmallVec with may_dangle Signed-off-by: Alejandro Vaz --- src/lib.rs | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b16ea380..4016d0e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1502,34 +1502,8 @@ impl Drop for DropDealloc<'_, Heap> { } } -#[cfg(feature = "may_dangle")] -unsafe impl<#[may_dangle] Item, const INLINE: usize, Heap: Allocator> Drop - for SmallVec -{ - fn drop(&mut self) { - let (length, on_heap) = self.length.parts(); - // SAFETY: the tag tells which member is active - let ptr = unsafe { self.raw.as_mut_ptr(on_heap) }; - // SAFETY: see above - unsafe { - let _drop_dealloc = if on_heap { - let capacity = self.raw.heap.1; - Some(DropDealloc { - ptr: NonNull::new_unchecked(ptr as *mut u8), - size_bytes: capacity * size_of::(), - align: align_of::(), - allocator: &self.allocator - }) - } else { - None - }; - core::ptr::slice_from_raw_parts_mut(ptr, length).drop_in_place(); - } - } -} - -#[cfg(not(feature = "may_dangle"))] -impl Drop for SmallVec { +#[cfg_attr(feature = "may-dangle", syntax(unsafe))] +impl<#[cfg_attr(feature = "may-dangle", may_dangle)] Item, const INLINE: usize, Heap: Allocator> Drop for SmallVec { fn drop(&mut self) { let (length, on_heap) = self.length.parts(); // SAFETY: the tag tells which member is active From e28049d493621d027f615002c7679fcdcdb21726 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:20:48 +0200 Subject: [PATCH 05/11] Refactor Drop implementation for SmallVec Signed-off-by: Alejandro Vaz --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4016d0e7..bcb24943 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1503,7 +1503,9 @@ impl Drop for DropDealloc<'_, Heap> { } #[cfg_attr(feature = "may-dangle", syntax(unsafe))] -impl<#[cfg_attr(feature = "may-dangle", may_dangle)] Item, const INLINE: usize, Heap: Allocator> Drop for SmallVec { +impl<#[cfg_attr(feature = "may-dangle", may_dangle)] Item, const INLINE: usize, Heap: Allocator> + Drop for SmallVec +{ fn drop(&mut self) { let (length, on_heap) = self.length.parts(); // SAFETY: the tag tells which member is active From 784b1fa728f8540eee62292b5b09fc33fa9983ea Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:50:31 +0200 Subject: [PATCH 06/11] Update lib.rs Signed-off-by: Alejandro Vaz --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bcb24943..9627a656 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -454,8 +454,8 @@ impl SmallVec { tail_start: end, tail_len: length - end, iter: range_slice.iter(), - // Since self is a &mut, passing it to a function would invalidate the slice - // iterator. + // Since self is a &mut, passing it to a function would + // invalidate the slice iterator. vec: NonNull::new_unchecked(self as *mut _) } } From 2d75ed1fd9a53fdebb91eb7562752585c2b33b26 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:53:34 +0200 Subject: [PATCH 07/11] Update lib.rs Signed-off-by: Alejandro Vaz --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9627a656..a4c18d43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1503,8 +1503,8 @@ impl Drop for DropDealloc<'_, Heap> { } #[cfg_attr(feature = "may-dangle", syntax(unsafe))] -impl<#[cfg_attr(feature = "may-dangle", may_dangle)] Item, const INLINE: usize, Heap: Allocator> - Drop for SmallVec +impl<#[cfg_attr(feature = "may-dangle", may_dangle)] Item, const INLINE: usize, Heap: Allocator> + Drop for SmallVec { fn drop(&mut self) { let (length, on_heap) = self.length.parts(); From 4f8603f93a24e8710b6aa812a1e80a2e6c54807c Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:53:57 +0200 Subject: [PATCH 08/11] Rename may_dangle.rs to maydangle.rs Signed-off-by: Alejandro Vaz --- tests/{may_dangle.rs => maydangle.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{may_dangle.rs => maydangle.rs} (100%) diff --git a/tests/may_dangle.rs b/tests/maydangle.rs similarity index 100% rename from tests/may_dangle.rs rename to tests/maydangle.rs From ff3fb1ab1e1dfcfb1558261c8268e57afcf9ee49 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:54:26 +0200 Subject: [PATCH 09/11] Remove feature flag from maydangle test Signed-off-by: Alejandro Vaz --- tests/maydangle.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/maydangle.rs b/tests/maydangle.rs index 58b40146..fcd7dd6d 100644 --- a/tests/maydangle.rs +++ b/tests/maydangle.rs @@ -1,5 +1,3 @@ -#![cfg(feature = "may_dangle")] - use smallvec::SmallVec; #[derive(Default)] From 044f79dde5cafb0040254b264e6f09415225c5e4 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:55:39 +0200 Subject: [PATCH 10/11] Add maydangle test with required features Signed-off-by: Alejandro Vaz --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 7b256fc8..5f4eb391 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,10 @@ required-features = ["encase"] name = "equivalent" required-features = ["equivalent"] +[[test]] +name = "maydangle" +required-features = ["may-dangle"] + [[test]] name = "rayon" required-features = ["rayon"] From 3af155f7a8dac41e04e3d3e4f7e69a80a97d8811 Mon Sep 17 00:00:00 2001 From: Alejandro Vaz Date: Fri, 23 Oct 2026 13:58:13 +0200 Subject: [PATCH 11/11] Improve comments in spec_from_iter function Refactor comments for clarity in spec_from_iter function. Signed-off-by: Alejandro Vaz --- src/specialization.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/specialization.rs b/src/specialization.rs index 525da0c4..452fc37e 100644 --- a/src/specialization.rs +++ b/src/specialization.rs @@ -257,10 +257,10 @@ where I: TrustedLen fn spec_from_iter(iter: I) -> Self { let mut v = match iter.size_hint() { (_, Some(upper)) => SmallVec::with_capacity(upper), - // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there - // are more than `usize::MAX` elements. - // Since the previous branch would eagerly panic if the capacity is too large - // (via `with_capacity`) we do the same here. + // TrustedLen contract guarantees that `size_hint() == (_, None)` + // means that there are more than `usize::MAX` elements. + // Since the previous branch would eagerly panic if the capacity is + // too large (via `with_capacity`) we do the same here. _ => panic!("capacity overflow") }; // Reuse the extend specialization for TrustedLen.