diff --git a/Cargo.toml b/Cargo.toml index 3ded9bd5..5f4eb391 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ strip = false allocator-api = [] allocator-api2 = ["allocator-api", "dep:allocator-api2"] internals = [] +may-dangle = [] proptest = ["dep:proptest", "std"] rayon = ["dep:rayon", "std"] serde = ["dep:serde_core"] @@ -80,6 +81,10 @@ required-features = ["encase"] name = "equivalent" required-features = ["equivalent"] +[[test]] +name = "maydangle" +required-features = ["may-dangle"] + [[test]] name = "rayon" required-features = ["rayon"] diff --git a/src/lib.rs b/src/lib.rs index 7f094fb2..a4c18d43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +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( all(feature = "allocator-api", not(feature = "allocator-api2")), feature(allocator_api) @@ -453,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 _) } } @@ -1501,7 +1502,10 @@ impl Drop for DropDealloc<'_, Heap> { } } -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 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. diff --git a/tests/maydangle.rs b/tests/maydangle.rs new file mode 100644 index 00000000..fcd7dd6d --- /dev/null +++ b/tests/maydangle.rs @@ -0,0 +1,13 @@ +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); +}