From 478a8a01249f79c0766041871024ef97734ed336 Mon Sep 17 00:00:00 2001 From: Benjamin Scherer Date: Wed, 15 Jul 2020 21:02:26 -0600 Subject: [PATCH] Make capacity() methods not rely on Array::CAPACITY (#83) * Make capacity() methods not rely on Array::CAPACITY Because Array isn't an unsafe trait, unsafe code cannot depend on the length of a slice produced by Array::as_slice to be at least as long as Array::CAPACITY. This means that unsafe code also cannot depend on capacity() methods that return Array::CAPACITY. Returning the result of a slice len() call ensures that if nothing else, with a sound implementation of Array, capacity() methods will return a valid length for a sub-slice of the backing array. * Add comments explaining choice against using Array::CAPACITY --- src/arrayvec.rs | 5 ++++- src/tinyvec.rs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 8c3c859..2d8dadb 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -194,7 +194,10 @@ impl ArrayVec { #[inline(always)] #[must_use] pub fn capacity(&self) -> usize { - A::CAPACITY + // Note: This shouldn't use A::CAPACITY, because unsafe code can't rely on + // any Array invariants. This ensures that at the very least, the returned + // value is a valid length for a subslice of the backing array. + self.data.as_slice().len() } /// Truncates the `ArrayVec` down to length 0. diff --git a/src/tinyvec.rs b/src/tinyvec.rs index 5bf9e05..5512704 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -212,7 +212,8 @@ impl TinyVec { #[must_use] pub fn capacity(&self) -> usize { match self { - TinyVec::Inline(_) => A::CAPACITY, + // Note: this shouldn't use A::CAPACITY. See ArrayVec::capacity(). + TinyVec::Inline(v) => v.capacity(), TinyVec::Heap(v) => v.capacity(), } }