From fb92d14ab4c4717192016637a01bf2d8cbf0c305 Mon Sep 17 00:00:00 2001 From: Benjamin Scherer Date: Thu, 18 Jun 2020 09:22:21 -0600 Subject: [PATCH] Modify tiny_vec! to avoid error on non-Copy types (#74) * Modify tiny_vec! to avoid error on non-Copy types Using $elem in two closures in the previous version of the macro created errors when using types that don't implement Copy. Moving the decision of whether to allocate or use an inline array to the macro invocation resolves this error as the borrow checker can see that both branches are never taken together. * Add test for tiny_vec! using non-Copy types * Fix inference issue * Use full crate path in tiny_vec! --- src/tinyvec.rs | 25 +++++++++++++------------ tests/tinyvec.rs | 7 +++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/tinyvec.rs b/src/tinyvec.rs index 7fe65ee..faf9a66 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -46,11 +46,10 @@ macro_rules! tiny_vec { const INVOKED_ELEM_COUNT: usize = 0 $( + { let _ = stringify!($elem); 1 })*; // If we have more `$elem` than the `CAPACITY` we will simply go directly // to constructing on the heap. - let av: $crate::TinyVec<$array_type> = $crate::TinyVec::from_either_with_capacity( - INVOKED_ELEM_COUNT, - #[inline(always)] || $crate::array_vec!($array_type, $($elem),*), - #[inline(always)] || vec!($($elem),*)); - av + match $crate::TinyVec::constructor_for_capacity(INVOKED_ELEM_COUNT) { + $crate::TinyVecConstructor::Inline(f) => f($crate::array_vec!($array_type, $($elem),*)), + $crate::TinyVecConstructor::Heap(f) => f(vec!($($elem),*)), + } } }; () => { @@ -61,6 +60,12 @@ macro_rules! tiny_vec { }; } +#[doc(hidden)] // Internal implementation details of `tiny_vec!` +pub enum TinyVecConstructor { + Inline(fn(ArrayVec) -> TinyVec), + Heap(fn(Vec) -> TinyVec), +} + /// A vector that starts inline, but can automatically move to the heap. /// /// * Requires the `alloc` feature @@ -344,15 +349,11 @@ impl TinyVec { #[inline(always)] #[doc(hidden)] // Internal implementation details of `tiny_vec!` - pub fn from_either_with_capacity( - cap: usize, - make_array: impl FnOnce() -> ArrayVec, - make_vec: impl FnOnce() -> Vec, - ) -> Self { + pub fn constructor_for_capacity(cap: usize) -> TinyVecConstructor { if cap <= A::CAPACITY { - TinyVec::Inline(make_array()) + TinyVecConstructor::Inline(TinyVec::Inline) } else { - TinyVec::Heap(make_vec()) + TinyVecConstructor::Heap(TinyVec::Heap) } } diff --git a/tests/tinyvec.rs b/tests/tinyvec.rs index ca05b92..ce41a69 100644 --- a/tests/tinyvec.rs +++ b/tests/tinyvec.rs @@ -93,3 +93,10 @@ fn TinyVec_from_array() { let tv = TinyVec::from(array); assert_eq!(&array, &tv[..]); } + +#[test] +fn TinyVec_macro_non_copy() { + // must use a variable here to avoid macro shenanigans + let s = String::new(); + let _: TinyVec<[String; 10]> = tiny_vec!([String; 10], s); +}