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!
This commit is contained in:
Benjamin Scherer
2020-06-18 09:22:21 -06:00
committed by GitHub
parent 726167b3a9
commit fb92d14ab4
2 changed files with 20 additions and 12 deletions
+13 -12
View File
@@ -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<A: Array> {
Inline(fn(ArrayVec<A>) -> TinyVec<A>),
Heap(fn(Vec<A::Item>) -> TinyVec<A>),
}
/// A vector that starts inline, but can automatically move to the heap.
///
/// * Requires the `alloc` feature
@@ -344,15 +349,11 @@ impl<A: Array> TinyVec<A> {
#[inline(always)]
#[doc(hidden)] // Internal implementation details of `tiny_vec!`
pub fn from_either_with_capacity(
cap: usize,
make_array: impl FnOnce() -> ArrayVec<A>,
make_vec: impl FnOnce() -> Vec<A::Item>,
) -> Self {
pub fn constructor_for_capacity(cap: usize) -> TinyVecConstructor<A> {
if cap <= A::CAPACITY {
TinyVec::Inline(make_array())
TinyVecConstructor::Inline(TinyVec::Inline)
} else {
TinyVec::Heap(make_vec())
TinyVecConstructor::Heap(TinyVec::Heap)
}
}
+7
View File
@@ -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);
}