diff --git a/src/array_string.rs b/src/array_string.rs
index 1144360..fcf0836 100644
--- a/src/array_string.rs
+++ b/src/array_string.rs
@@ -11,12 +11,12 @@ use std::str;
 use std::str::FromStr;
 use std::str::Utf8Error;
 
+use crate::len_type::{check_cap_fits_in_len_type, DefaultLenType, LenUint};
 use crate::CapacityError;
-use crate::LenUint;
 use crate::char::encode_utf8;
 use crate::utils::MakeMaybeUninit;
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 use serde::{Serialize, Deserialize, Serializer, Deserializer};
 
 
@@ -32,21 +32,21 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
 /// if needed.
 #[derive(Copy)]
 #[repr(C)]
-pub struct ArrayString<const CAP: usize> {
+pub struct ArrayString<const CAP: usize, LenType: LenUint = DefaultLenType<CAP>> {
     // the `len` first elements of the array are initialized
-    len: LenUint,
+    len: LenType,
     xs: [MaybeUninit<u8>; CAP],
 }
 
-impl<const CAP: usize> Default for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Default for ArrayString<CAP, LenType>
 {
     /// Return an empty `ArrayString`
-    fn default() -> ArrayString<CAP> {
+    fn default() -> Self {
         ArrayString::new()
     }
 }
 
-impl<const CAP: usize> ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> ArrayString<CAP, LenType>
 {
     /// Create a new empty `ArrayString`.
     ///
@@ -60,11 +60,14 @@ impl<const CAP: usize> ArrayString<CAP>
     /// assert_eq!(&string[..], "foo");
     /// assert_eq!(string.capacity(), 16);
     /// ```
-    pub fn new() -> ArrayString<CAP> {
-        assert_capacity_limit!(CAP);
-        unsafe {
-            ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
-        }
+    ///
+    /// If you provide a capacity greater than a length type, this will fail at compile time.
+    /// ```compile_fail
+    /// let string = arrayvec::ArrayString::<256, u8>::new();
+    /// ```
+    pub fn new() -> Self {
+        check_cap_fits_in_len_type::<LenType, CAP>();
+        ArrayString { len: LenType::from_usize(0), xs: MakeMaybeUninit::ARRAY }
     }
 
     /// Create a new empty `ArrayString` (const fn).
@@ -74,20 +77,20 @@ impl<const CAP: usize> ArrayString<CAP>
     /// ```
     /// use arrayvec::ArrayString;
     ///
-    /// static ARRAY: ArrayString<1024> = ArrayString::new_const();
+    /// const ARRAY: ArrayString<1024> = ArrayString::new_const();
     /// ```
-    pub const fn new_const() -> ArrayString<CAP> {
-        assert_capacity_limit_const!(CAP);
-        ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 }
+    pub const fn new_const() -> Self {
+        check_cap_fits_in_len_type::<LenType, CAP>();
+        ArrayString { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY }
     }
 
     /// Return the length of the string.
     #[inline]
-    pub const fn len(&self) -> usize { self.len as usize }
+    pub fn len(&self) -> usize { LenType::to_usize(self.len) }
 
     /// Returns whether the string is empty.
     #[inline]
-    pub const fn is_empty(&self) -> bool { self.len() == 0 }
+    pub fn is_empty(&self) -> bool { self.len == LenType::ZERO }
 
     /// Create a new `ArrayString` from a `str`.
     ///
@@ -116,7 +119,7 @@ impl<const CAP: usize> ArrayString<CAP>
     /// ```
     /// use arrayvec::ArrayString;
     ///
-    /// let string = ArrayString::from_byte_string(b"hello world").unwrap();
+    /// let string = ArrayString::<11>::from_byte_string(b"hello world").unwrap();
     /// ```
     pub fn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> {
         let len = str::from_utf8(b)?.len();
@@ -139,15 +142,20 @@ impl<const CAP: usize> ArrayString<CAP>
     /// let string = ArrayString::<16>::zero_filled();
     /// assert_eq!(string.len(), 16);
     /// ```
+    ///
+    /// If you provide a capacity greater than a length type, this will fail at compile time.
+    /// ```compile_fail
+    /// let string = arrayvec::ArrayString::<256, u8>::zero_filled();
+    /// ```
     #[inline]
     pub fn zero_filled() -> Self {
-        assert_capacity_limit!(CAP);
-        // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and
+        check_cap_fits_in_len_type::<LenType, CAP>();
+        // SAFETY: `check_cap_fits_in_len_type` asserts that `len` won't overflow and
         // `zeroed` fully fills the array with nulls.
         unsafe {
             ArrayString {
                 xs: MaybeUninit::zeroed().assume_init(),
-                len: CAP as _
+                len: LenType::from_usize(CAP),
             }
         }
     }
@@ -173,7 +181,7 @@ impl<const CAP: usize> ArrayString<CAP>
     /// string.push_str("A");
     /// assert!(string.is_full());
     /// ```
-    pub const fn is_full(&self) -> bool { self.len() == self.capacity() }
+    pub fn is_full(&self) -> bool { self.len() == self.capacity() }
 
     /// Returns the capacity left in the `ArrayString`.
     ///
@@ -184,7 +192,7 @@ impl<const CAP: usize> ArrayString<CAP>
     /// string.pop();
     /// assert_eq!(string.remaining_capacity(), 1);
     /// ```
-    pub const fn remaining_capacity(&self) -> usize {
+    pub fn remaining_capacity(&self) -> usize {
         self.capacity() - self.len()
     }
 
@@ -299,7 +307,7 @@ impl<const CAP: usize> ArrayString<CAP>
     ///
     /// ```
     /// use arrayvec::ArrayString;
-    /// 
+    ///
     /// let mut s = ArrayString::<3>::from("foo").unwrap();
     ///
     /// assert_eq!(s.pop(), Some('o'));
@@ -339,7 +347,7 @@ impl<const CAP: usize> ArrayString<CAP>
     pub fn truncate(&mut self, new_len: usize) {
         if new_len <= self.len() {
             assert!(self.is_char_boundary(new_len));
-            unsafe { 
+            unsafe {
                 // In libstd truncate is called on the underlying vector,
                 // which in turns drops each element.
                 // As we know we don't have to worry about Drop,
@@ -359,7 +367,7 @@ impl<const CAP: usize> ArrayString<CAP>
     ///
     /// ```
     /// use arrayvec::ArrayString;
-    /// 
+    ///
     /// let mut s = ArrayString::<3>::from("foo").unwrap();
     ///
     /// assert_eq!(s.remove(0), 'f');
@@ -402,7 +410,7 @@ impl<const CAP: usize> ArrayString<CAP>
     pub unsafe fn set_len(&mut self, length: usize) {
         // type invariant that capacity always fits in LenUint
         debug_assert!(length <= self.capacity());
-        self.len = length as LenUint;
+        self.len = LenUint::from_usize(length);
     }
 
     /// Return a string slice of the whole `ArrayString`.
@@ -426,7 +434,7 @@ impl<const CAP: usize> ArrayString<CAP>
     }
 }
 
-impl<const CAP: usize> Deref for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Deref for ArrayString<CAP, LenType>
 {
     type Target = str;
     #[inline]
@@ -438,7 +446,7 @@ impl<const CAP: usize> Deref for ArrayString<CAP>
     }
 }
 
-impl<const CAP: usize> DerefMut for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> DerefMut for ArrayString<CAP, LenType>
 {
     #[inline]
     fn deref_mut(&mut self) -> &mut str {
@@ -450,64 +458,64 @@ impl<const CAP: usize> DerefMut for ArrayString<CAP>
     }
 }
 
-impl<const CAP: usize> PartialEq for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> PartialEq for ArrayString<CAP, LenType>
 {
     fn eq(&self, rhs: &Self) -> bool {
         **self == **rhs
     }
 }
 
-impl<const CAP: usize> PartialEq<str> for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> PartialEq<str> for ArrayString<CAP, LenType>
 {
     fn eq(&self, rhs: &str) -> bool {
         &**self == rhs
     }
 }
 
-impl<const CAP: usize> PartialEq<ArrayString<CAP>> for str
+impl<const CAP: usize, LenType: LenUint> PartialEq<ArrayString<CAP, LenType>> for str
 {
-    fn eq(&self, rhs: &ArrayString<CAP>) -> bool {
+    fn eq(&self, rhs: &ArrayString<CAP, LenType>) -> bool {
         self == &**rhs
     }
 }
 
-impl<const CAP: usize> Eq for ArrayString<CAP> 
-{ }
+impl<const CAP: usize, LenType: LenUint> Eq for ArrayString<CAP, LenType>
+{}
 
-impl<const CAP: usize> Hash for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Hash for ArrayString<CAP, LenType>
 {
     fn hash<H: Hasher>(&self, h: &mut H) {
         (**self).hash(h)
     }
 }
 
-impl<const CAP: usize> Borrow<str> for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Borrow<str> for ArrayString<CAP, LenType>
 {
     fn borrow(&self) -> &str { self }
 }
 
-impl<const CAP: usize> BorrowMut<str> for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> BorrowMut<str> for ArrayString<CAP, LenType>
 {
     fn borrow_mut(&mut self) -> &mut str { self }
 }
 
-impl<const CAP: usize> AsRef<str> for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> AsRef<str> for ArrayString<CAP, LenType>
 {
     fn as_ref(&self) -> &str { self }
 }
 
-impl<const CAP: usize> fmt::Debug for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> fmt::Debug for ArrayString<CAP, LenType>
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
 }
 
-impl<const CAP: usize> fmt::Display for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> fmt::Display for ArrayString<CAP, LenType>
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
 }
 
 /// `Write` appends written data to the end of the string.
-impl<const CAP: usize> fmt::Write for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> fmt::Write for ArrayString<CAP, LenType>
 {
     fn write_char(&mut self, c: char) -> fmt::Result {
         self.try_push(c).map_err(|_| fmt::Error)
@@ -518,9 +526,9 @@ impl<const CAP: usize> fmt::Write for ArrayString<CAP>
     }
 }
 
-impl<const CAP: usize> Clone for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Clone for ArrayString<CAP, LenType>
 {
-    fn clone(&self) -> ArrayString<CAP> {
+    fn clone(&self) -> ArrayString<CAP, LenType> {
         *self
     }
     fn clone_from(&mut self, rhs: &Self) {
@@ -530,7 +538,7 @@ impl<const CAP: usize> Clone for ArrayString<CAP>
     }
 }
 
-impl<const CAP: usize> PartialOrd for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> PartialOrd for ArrayString<CAP, LenType>
 {
     fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
         (**self).partial_cmp(&**rhs)
@@ -541,7 +549,7 @@ impl<const CAP: usize> PartialOrd for ArrayString<CAP>
     fn ge(&self, rhs: &Self) -> bool { **self >= **rhs }
 }
 
-impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> PartialOrd<str> for ArrayString<CAP, LenType>
 {
     fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> {
         (**self).partial_cmp(rhs)
@@ -552,25 +560,25 @@ impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP>
     fn ge(&self, rhs: &str) -> bool { &**self >= rhs }
 }
 
-impl<const CAP: usize> PartialOrd<ArrayString<CAP>> for str
+impl<const CAP: usize, LenType: LenUint> PartialOrd<ArrayString<CAP, LenType>> for str
 {
-    fn partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering> {
+    fn partial_cmp(&self, rhs: &ArrayString<CAP, LenType>) -> Option<cmp::Ordering> {
         self.partial_cmp(&**rhs)
     }
-    fn lt(&self, rhs: &ArrayString<CAP>) -> bool { self < &**rhs }
-    fn le(&self, rhs: &ArrayString<CAP>) -> bool { self <= &**rhs }
-    fn gt(&self, rhs: &ArrayString<CAP>) -> bool { self > &**rhs }
-    fn ge(&self, rhs: &ArrayString<CAP>) -> bool { self >= &**rhs }
+    fn lt(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self < &**rhs }
+    fn le(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self <= &**rhs }
+    fn gt(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self > &**rhs }
+    fn ge(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self >= &**rhs }
 }
 
-impl<const CAP: usize> Ord for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Ord for ArrayString<CAP, LenType>
 {
     fn cmp(&self, rhs: &Self) -> cmp::Ordering {
         (**self).cmp(&**rhs)
     }
 }
 
-impl<const CAP: usize> FromStr for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> FromStr for ArrayString<CAP, LenType>
 {
     type Err = CapacityError;
 
@@ -579,9 +587,9 @@ impl<const CAP: usize> FromStr for ArrayString<CAP>
     }
 }
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 /// Requires crate feature `"serde"`
-impl<const CAP: usize> Serialize for ArrayString<CAP>
+impl<const CAP: usize, LenType: LenUint> Serialize for ArrayString<CAP, LenType>
 {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         where S: Serializer
@@ -590,9 +598,9 @@ impl<const CAP: usize> Serialize for ArrayString<CAP>
     }
 }
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 /// Requires crate feature `"serde"`
-impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> 
+impl<'de, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayString<CAP, LenType>
 {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
         where D: Deserializer<'de>
@@ -600,10 +608,10 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP>
         use serde::de::{self, Visitor};
         use std::marker::PhantomData;
 
-        struct ArrayStringVisitor<const CAP: usize>(PhantomData<[u8; CAP]>);
+        struct ArrayStringVisitor<const CAP: usize, LenType: LenUint>(PhantomData<([u8; CAP], LenType)>);
 
-        impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor<CAP> {
-            type Value = ArrayString<CAP>;
+        impl<'de, const CAP: usize, LenType: LenUint> Visitor<'de> for ArrayStringVisitor<CAP, LenType> {
+            type Value = ArrayString<CAP, LenType>;
 
             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                 write!(formatter, "a string no more than {} bytes long", CAP)
@@ -630,7 +638,7 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP>
 
 #[cfg(feature = "borsh")]
 /// Requires crate feature `"borsh"`
-impl<const CAP: usize> borsh::BorshSerialize for ArrayString<CAP> {
+impl<const CAP: usize, LenType: LenUint> borsh::BorshSerialize for ArrayString<CAP, LenType> {
     fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> {
         <str as borsh::BorshSerialize>::serialize(&*self, writer)
     }
@@ -638,14 +646,14 @@ impl<const CAP: usize> borsh::BorshSerialize for ArrayString<CAP> {
 
 #[cfg(feature = "borsh")]
 /// Requires crate feature `"borsh"`
-impl<const CAP: usize> borsh::BorshDeserialize for ArrayString<CAP> {
+impl<const CAP: usize, LenType: LenUint> borsh::BorshDeserialize for ArrayString<CAP, LenType> {
     fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> borsh::io::Result<Self> {
         let len = <u32 as borsh::BorshDeserialize>::deserialize_reader(reader)? as usize;
         if len > CAP {
             return Err(borsh::io::Error::new(
                 borsh::io::ErrorKind::InvalidData,
                 format!("Expected a string no more than {} bytes long", CAP),
-            ))
+            ));
         }
 
         let mut buf = [0u8; CAP];
@@ -659,7 +667,7 @@ impl<const CAP: usize> borsh::BorshDeserialize for ArrayString<CAP> {
     }
 }
 
-impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP>
+impl<'a, const CAP: usize, LenType: LenUint> TryFrom<&'a str> for ArrayString<CAP, LenType>
 {
     type Error = CapacityError<&'a str>;
 
@@ -670,7 +678,7 @@ impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP>
     }
 }
 
-impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP>
+impl<'a, const CAP: usize, LenType: LenUint> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP, LenType>
 {
     type Error = CapacityError<fmt::Error>;
 
@@ -697,7 +705,7 @@ impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP>
 /// unsafe { string.set_len(string.capacity()) };
 /// assert_eq!(&*string, "\0\0\0\0\0\0");
 /// ```
-impl<const CAP: usize> zeroize::Zeroize for ArrayString<CAP> {
+impl<const CAP: usize, LenType: LenUint> zeroize::Zeroize for ArrayString<CAP, LenType> {
     fn zeroize(&mut self) {
         // There are no elements to drop
         self.clear();
diff --git a/src/arrayvec.rs b/src/arrayvec.rs
index e87b3ef..f7993cf 100644
--- a/src/arrayvec.rs
+++ b/src/arrayvec.rs
@@ -1,4 +1,3 @@
-
 use std::cmp;
 use std::iter;
 use std::mem;
@@ -11,16 +10,17 @@ use std::borrow::{Borrow, BorrowMut};
 use std::hash::{Hash, Hasher};
 use std::fmt;
 
-#[cfg(feature="std")]
+#[cfg(feature = "std")]
 use std::io;
 
 use std::mem::ManuallyDrop;
 use std::mem::MaybeUninit;
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 use serde::{Serialize, Deserialize, Serializer, Deserializer};
 
-use crate::LenUint;
+use crate::len_type::{check_cap_fits_in_len_type, ConstGenericSmuggler, CapToDefaultLenType};
+use crate::len_type::{LenUint, DefaultLenType};
 use crate::errors::CapacityError;
 use crate::arrayvec_impl::ArrayVecImpl;
 use crate::utils::MakeMaybeUninit;
@@ -40,13 +40,13 @@ use crate::utils::MakeMaybeUninit;
 /// It offers a simple API but also dereferences to a slice, so that the full slice API is
 /// available. The ArrayVec can be converted into a by value iterator.
 #[repr(C)]
-pub struct ArrayVec<T, const CAP: usize> {
-    len: LenUint,
+pub struct ArrayVec<T, const CAP: usize, LenT: LenUint = DefaultLenType<CAP>> {
+    len: LenT,
     // the `len` first elements of the array are initialized
     xs: [MaybeUninit<T>; CAP],
 }
 
-impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Drop for ArrayVec<T, CAP, LenType> {
     fn drop(&mut self) {
         self.clear();
 
@@ -61,7 +61,7 @@ macro_rules! panic_oob {
     }
 }
 
-impl<T, const CAP: usize> ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> ArrayVec<T, CAP, LenType> {
     /// Capacity
     const CAPACITY: usize = CAP;
 
@@ -80,11 +80,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// ```
     #[inline]
     #[track_caller]
-    pub fn new() -> ArrayVec<T, CAP> {
-        assert_capacity_limit!(CAP);
-        unsafe {
-            ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 }
-        }
+    pub fn new() -> Self {
+        check_cap_fits_in_len_type::<LenType, CAP>();
+        ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY }
     }
 
     /// Create a new empty `ArrayVec` (const fn).
@@ -96,9 +94,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     ///
     /// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const();
     /// ```
-    pub const fn new_const() -> ArrayVec<T, CAP> {
-        assert_capacity_limit_const!(CAP);
-        ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 }
+    pub const fn new_const() -> Self {
+        check_cap_fits_in_len_type::<LenType, CAP>();
+        ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY }
     }
 
     /// Return the number of elements in the `ArrayVec`.
@@ -111,7 +109,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// assert_eq!(array.len(), 2);
     /// ```
     #[inline(always)]
-    pub const fn len(&self) -> usize { self.len as usize }
+    pub fn len(&self) -> usize { self.len.to_usize() }
 
     /// Returns whether the `ArrayVec` is empty.
     ///
@@ -123,7 +121,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// assert_eq!(array.is_empty(), true);
     /// ```
     #[inline]
-    pub const fn is_empty(&self) -> bool { self.len() == 0 }
+    pub fn is_empty(&self) -> bool { self.len == LenType::ZERO }
 
     /// Return the capacity of the `ArrayVec`.
     ///
@@ -146,7 +144,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// array.push(1);
     /// assert!(array.is_full());
     /// ```
-    pub const fn is_full(&self) -> bool { self.len() == self.capacity() }
+    pub fn is_full(&self) -> bool { self.len() == self.capacity() }
 
     /// Returns the capacity left in the `ArrayVec`.
     ///
@@ -157,7 +155,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// array.pop();
     /// assert_eq!(array.remaining_capacity(), 1);
     /// ```
-    pub const fn remaining_capacity(&self) -> usize {
+    pub fn remaining_capacity(&self) -> usize {
         self.capacity() - self.len()
     }
 
@@ -472,21 +470,21 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
         let original_len = self.len();
         unsafe { self.set_len(0) };
 
-        struct BackshiftOnDrop<'a, T, const CAP: usize> {
-            v: &'a mut ArrayVec<T, CAP>,
+        struct BackshiftOnDrop<'a, T, const CAP: usize, LenType: LenUint> {
+            v: &'a mut ArrayVec<T, CAP, LenType>,
             processed_len: usize,
             deleted_cnt: usize,
             original_len: usize,
         }
 
-        impl<T, const CAP: usize> Drop for BackshiftOnDrop<'_, T, CAP> {
+        impl<T, const CAP: usize, LenType: LenUint> Drop for BackshiftOnDrop<'_, T, CAP, LenType> {
             fn drop(&mut self) {
                 if self.deleted_cnt > 0 {
                     unsafe {
                         ptr::copy(
                             self.v.as_ptr().add(self.processed_len),
                             self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt),
-                            self.original_len - self.processed_len
+                            self.original_len - self.processed_len,
                         );
                     }
                 }
@@ -499,9 +497,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
         let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len };
 
         #[inline(always)]
-        fn process_one<F: FnMut(&mut T) -> bool, T, const CAP: usize, const DELETED: bool>(
+        fn process_one<F: FnMut(&mut T) -> bool, T, const CAP: usize, const DELETED: bool, LenType: LenUint>(
             f: &mut F,
-            g: &mut BackshiftOnDrop<'_, T, CAP>
+            g: &mut BackshiftOnDrop<'_, T, CAP, LenType>,
         ) -> bool {
             let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) };
             if !f(unsafe { &mut *cur }) {
@@ -522,14 +520,14 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
 
         // Stage 1: Nothing was deleted.
         while g.processed_len != original_len {
-            if !process_one::<F, T, CAP, false>(&mut f, &mut g) {
+            if !process_one::<F, T, CAP, false, LenType>(&mut f, &mut g) {
                 break;
             }
         }
 
         // Stage 2: Some elements were deleted.
         while g.processed_len != original_len {
-            process_one::<F, T, CAP, true>(&mut f, &mut g);
+            process_one::<F, T, CAP, true, LenType>(&mut f, &mut g);
         }
 
         drop(g);
@@ -545,7 +543,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     pub unsafe fn set_len(&mut self, length: usize) {
         // type invariant that capacity always fits in LenUint
         debug_assert!(length <= self.capacity());
-        self.len = length as LenUint;
+        self.len = LenType::from_usize(length);
     }
 
     /// Copy all elements from the slice and append to the `ArrayVec`.
@@ -602,7 +600,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// assert_eq!(&v1[..], &[3]);
     /// assert_eq!(&v2[..], &[1, 2]);
     /// ```
-    pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP>
+    pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP, LenType>
         where R: RangeBounds<usize>
     {
         // Memory safety
@@ -629,7 +627,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
         self.drain_range(start, end)
     }
 
-    fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP>
+    fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP, LenType>
     {
         let len = self.len();
 
@@ -638,7 +636,8 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
 
         // Calling `set_len` creates a fresh and thus unique mutable references, making all
         // older aliases we created invalid. So we cannot call that function.
-        self.len = start as LenUint;
+        // safety: we just checked that the start is in bounds
+        self.len = LenType::from_usize(start);
 
         unsafe {
             Drain {
@@ -682,7 +681,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap());
     /// assert!(v.is_empty());
     /// ```
-    pub fn take(&mut self) -> Self  {
+    pub fn take(&mut self) -> Self {
         mem::replace(self, Self::new())
     }
 
@@ -707,15 +706,15 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> ArrayVecImpl for ArrayVec<T, CAP, LenType> {
     type Item = T;
     const CAPACITY: usize = CAP;
 
     fn len(&self) -> usize { self.len() }
 
     unsafe fn set_len(&mut self, length: usize) {
-        debug_assert!(length <= CAP);
-        self.len = length as LenUint;
+        debug_assert!(length <= CAP, "length {} exceeds capacity {}", length, CAP);
+        self.len = LenType::from_usize(length);
     }
 
     fn as_ptr(&self) -> *const Self::Item {
@@ -727,7 +726,7 @@ impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Deref for ArrayVec<T, CAP, LenType> {
     type Target = [T];
     #[inline]
     fn deref(&self) -> &Self::Target {
@@ -735,7 +734,7 @@ impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> DerefMut for ArrayVec<T, CAP, LenType> {
     #[inline]
     fn deref_mut(&mut self) -> &mut Self::Target {
         self.as_mut_slice()
@@ -752,11 +751,13 @@ impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> {
 /// assert_eq!(array.len(), 3);
 /// assert_eq!(array.capacity(), 3);
 /// ```
-impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP>
+    where ConstGenericSmuggler<CAP>: CapToDefaultLenType
+{
     #[track_caller]
     fn from(array: [T; CAP]) -> Self {
         let array = ManuallyDrop::new(array);
-        let mut vec = <ArrayVec<T, CAP>>::new();
+        let mut vec = Self::new();
         unsafe {
             (&*array as *const [T; CAP] as *const [MaybeUninit<T>; CAP])
                 .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<T>; CAP], 1);
@@ -778,7 +779,7 @@ impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
 /// assert_eq!(array.len(), 3);
 /// assert_eq!(array.capacity(), 4);
 /// ```
-impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP>
+impl<T, const CAP: usize, LenType: LenUint> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP, LenType>
     where T: Clone,
 {
     type Error = CapacityError;
@@ -806,7 +807,7 @@ impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP>
 ///     // ...
 /// }
 /// ```
-impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> {
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> IntoIterator for &'a ArrayVec<T, CAP, LenType> {
     type Item = &'a T;
     type IntoIter = slice::Iter<'a, T>;
     fn into_iter(self) -> Self::IntoIter { self.iter() }
@@ -823,7 +824,7 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> {
 ///     // ...
 /// }
 /// ```
-impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> {
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> IntoIterator for &'a mut ArrayVec<T, CAP, LenType> {
     type Item = &'a mut T;
     type IntoIter = slice::IterMut<'a, T>;
     fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
@@ -840,11 +841,11 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> {
 ///     // ...
 /// }
 /// ```
-impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> IntoIterator for ArrayVec<T, CAP, LenType> {
     type Item = T;
-    type IntoIter = IntoIter<T, CAP>;
-    fn into_iter(self) -> IntoIter<T, CAP> {
-        IntoIter { index: 0, v: self, }
+    type IntoIter = IntoIter<T, CAP, LenType>;
+    fn into_iter(self) -> Self::IntoIter {
+        IntoIter { index: 0, v: self }
     }
 }
 
@@ -864,7 +865,7 @@ impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> {
 /// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) };
 /// assert_eq!(data, [0, 0, 0]);
 /// ```
-impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP> {
+impl<Z: zeroize::Zeroize, const CAP: usize, LenType: LenUint> zeroize::Zeroize for ArrayVec<Z, CAP, LenType> {
     fn zeroize(&mut self) {
         // Zeroize all the contained elements.
         self.iter_mut().zeroize();
@@ -876,11 +877,12 @@ impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP
 }
 
 /// By-value iterator for `ArrayVec`.
-pub struct IntoIter<T, const CAP: usize> {
+pub struct IntoIter<T, const CAP: usize, LenType: LenUint = DefaultLenType<CAP>> {
     index: usize,
-    v: ArrayVec<T, CAP>,
+    v: ArrayVec<T, CAP, LenType>,
 }
-impl<T, const CAP: usize> IntoIter<T, CAP> {
+
+impl<T, const CAP: usize, LenType: LenUint> IntoIter<T, CAP, LenType> {
     /// Returns the remaining items of this iterator as a slice.
     pub fn as_slice(&self) -> &[T] {
         &self.v[self.index..]
@@ -892,7 +894,7 @@ impl<T, const CAP: usize> IntoIter<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Iterator for IntoIter<T, CAP, LenType> {
     type Item = T;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -913,7 +915,7 @@ impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> DoubleEndedIterator for IntoIter<T, CAP, LenType> {
     fn next_back(&mut self) -> Option<Self::Item> {
         if self.index == self.v.len() {
             None
@@ -927,9 +929,9 @@ impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { }
+impl<T, const CAP: usize, LenType: LenUint> ExactSizeIterator for IntoIter<T, CAP, LenType> {}
 
-impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Drop for IntoIter<T, CAP, LenType> {
     fn drop(&mut self) {
         // panic safety: Set length to 0 before dropping elements.
         let index = self.index;
@@ -944,19 +946,19 @@ impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> Clone for IntoIter<T, CAP>
-where T: Clone,
+impl<T, const CAP: usize, LenType: LenUint> Clone for IntoIter<T, CAP, LenType>
+    where T: Clone,
 {
-    fn clone(&self) -> IntoIter<T, CAP> {
+    fn clone(&self) -> Self {
         let mut v = ArrayVec::new();
         v.extend_from_slice(&self.v[self.index..]);
         v.into_iter()
     }
 }
 
-impl<T, const CAP: usize> fmt::Debug for IntoIter<T, CAP>
-where
-    T: fmt::Debug,
+impl<T, const CAP: usize, LenType: LenUint> fmt::Debug for IntoIter<T, CAP, LenType>
+    where
+        T: fmt::Debug,
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_list()
@@ -966,20 +968,21 @@ where
 }
 
 /// A draining iterator for `ArrayVec`.
-pub struct Drain<'a, T: 'a, const CAP: usize> {
+pub struct Drain<'a, T: 'a, const CAP: usize, LenType: LenUint> {
     /// Index of tail to preserve
     tail_start: usize,
     /// Length of tail
     tail_len: usize,
     /// Current remaining range to remove
     iter: slice::Iter<'a, T>,
-    vec: *mut ArrayVec<T, CAP>,
+    vec: *mut ArrayVec<T, CAP, LenType>,
 }
 
-unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {}
-unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {}
+unsafe impl<'a, T: Sync, const CAP: usize, LenType: LenUint> Sync for Drain<'a, T, CAP, LenType> {}
 
-impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> {
+unsafe impl<'a, T: Send, const CAP: usize, LenType: LenUint> Send for Drain<'a, T, CAP, LenType> {}
+
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> Iterator for Drain<'a, T, CAP, LenType> {
     type Item = T;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -995,7 +998,7 @@ impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> {
     }
 }
 
-impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP>
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> DoubleEndedIterator for Drain<'a, T, CAP, LenType>
 {
     fn next_back(&mut self) -> Option<Self::Item> {
         self.iter.next_back().map(|elt|
@@ -1006,14 +1009,14 @@ impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP>
     }
 }
 
-impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {}
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> ExactSizeIterator for Drain<'a, T, CAP, LenType> {}
 
-impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> {
+impl<'a, T: 'a, const CAP: usize, LenType: LenUint> Drop for Drain<'a, T, CAP, LenType> {
     fn drop(&mut self) {
         // len is currently 0 so panicking while dropping will not cause a double drop.
 
         // exhaust self first
-        while let Some(_) = self.next() { }
+        while let Some(_) = self.next() {}
 
         if self.tail_len > 0 {
             unsafe {
@@ -1046,13 +1049,12 @@ impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F>
 }
 
 
-
 /// Extend the `ArrayVec` with an iterator.
-/// 
+///
 /// ***Panics*** if extending the vector exceeds its capacity.
-impl<T, const CAP: usize> Extend<T> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Extend<T> for ArrayVec<T, CAP, LenType> {
     /// Extend the `ArrayVec` with an iterator.
-    /// 
+    ///
     /// ***Panics*** if extending the vector exceeds its capacity.
     #[track_caller]
     fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
@@ -1069,7 +1071,7 @@ fn extend_panic() {
     panic!("ArrayVec: capacity exceeded in extend/from_iter");
 }
 
-impl<T, const CAP: usize> ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> ArrayVec<T, CAP, LenType> {
     /// Extend the arrayvec from the iterable.
     ///
     /// ## Safety
@@ -1078,7 +1080,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
     /// The caller must ensure the length of the input fits in the capacity.
     #[track_caller]
     pub(crate) unsafe fn extend_from_iter<I, const CHECK: bool>(&mut self, iterable: I)
-        where I: IntoIterator<Item = T>
+        where I: IntoIterator<Item=T>
     {
         let take = self.capacity() - self.len();
         let len = self.len();
@@ -1092,8 +1094,8 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
             value: &mut self.len,
             data: len,
             f: move |&len, self_len| {
-                **self_len = len as LenUint;
-            }
+                **self_len = LenUint::from_usize(len);
+            },
         };
         let mut iter = iterable.into_iter();
         loop {
@@ -1136,11 +1138,11 @@ unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T {
 }
 
 /// Create an `ArrayVec` from an iterator.
-/// 
+///
 /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
-impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> iter::FromIterator<T> for ArrayVec<T, CAP, LenType> {
     /// Create an `ArrayVec` from an iterator.
-    /// 
+    ///
     /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
     fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
         let mut array = ArrayVec::new();
@@ -1149,7 +1151,7 @@ impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
     }
 }
 
-impl<T, const CAP: usize> Clone for ArrayVec<T, CAP>
+impl<T, const CAP: usize, LenType: LenUint> Clone for ArrayVec<T, CAP, LenType>
     where T: Clone
 {
     fn clone(&self) -> Self {
@@ -1171,7 +1173,7 @@ impl<T, const CAP: usize> Clone for ArrayVec<T, CAP>
     }
 }
 
-impl<T, const CAP: usize> Hash for ArrayVec<T, CAP>
+impl<T, const CAP: usize, LenType: LenUint> Hash for ArrayVec<T, CAP, LenType>
     where T: Hash
 {
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -1179,7 +1181,7 @@ impl<T, const CAP: usize> Hash for ArrayVec<T, CAP>
     }
 }
 
-impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP>
+impl<T, const CAP: usize, LenType: LenUint> PartialEq for ArrayVec<T, CAP, LenType>
     where T: PartialEq
 {
     fn eq(&self, other: &Self) -> bool {
@@ -1187,7 +1189,7 @@ impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP>
     }
 }
 
-impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP>
+impl<T, const CAP: usize, LenType: LenUint> PartialEq<[T]> for ArrayVec<T, CAP, LenType>
     where T: PartialEq
 {
     fn eq(&self, other: &[T]) -> bool {
@@ -1195,36 +1197,36 @@ impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP>
     }
 }
 
-impl<T, const CAP: usize> Eq for ArrayVec<T, CAP> where T: Eq { }
+impl<T, const CAP: usize, LenType: LenUint> Eq for ArrayVec<T, CAP, LenType> where T: Eq {}
 
-impl<T, const CAP: usize> Borrow<[T]> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Borrow<[T]> for ArrayVec<T, CAP, LenType> {
     fn borrow(&self) -> &[T] { self }
 }
 
-impl<T, const CAP: usize> BorrowMut<[T]> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> BorrowMut<[T]> for ArrayVec<T, CAP, LenType> {
     fn borrow_mut(&mut self) -> &mut [T] { self }
 }
 
-impl<T, const CAP: usize> AsRef<[T]> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> AsRef<[T]> for ArrayVec<T, CAP, LenType> {
     fn as_ref(&self) -> &[T] { self }
 }
 
-impl<T, const CAP: usize> AsMut<[T]> for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> AsMut<[T]> for ArrayVec<T, CAP, LenType> {
     fn as_mut(&mut self) -> &mut [T] { self }
 }
 
-impl<T, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> where T: fmt::Debug {
+impl<T, const CAP: usize, LenType: LenUint> fmt::Debug for ArrayVec<T, CAP, LenType> where T: fmt::Debug {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
 }
 
-impl<T, const CAP: usize> Default for ArrayVec<T, CAP> {
+impl<T, const CAP: usize, LenType: LenUint> Default for ArrayVec<T, CAP, LenType> {
     /// Return an empty array
-    fn default() -> ArrayVec<T, CAP> {
+    fn default() -> Self {
         ArrayVec::new()
     }
 }
 
-impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd {
+impl<T, const CAP: usize, LenType: LenUint> PartialOrd for ArrayVec<T, CAP, LenType> where T: PartialOrd {
     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
         (**self).partial_cmp(other)
     }
@@ -1246,17 +1248,17 @@ impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd {
     }
 }
 
-impl<T, const CAP: usize> Ord for ArrayVec<T, CAP> where T: Ord {
+impl<T, const CAP: usize, LenType: LenUint> Ord for ArrayVec<T, CAP, LenType> where T: Ord {
     fn cmp(&self, other: &Self) -> cmp::Ordering {
         (**self).cmp(other)
     }
 }
 
-#[cfg(feature="std")]
+#[cfg(feature = "std")]
 /// `Write` appends written data to the end of the vector.
 ///
 /// Requires `features="std"`.
-impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> {
+impl<const CAP: usize, LenType: LenUint> io::Write for ArrayVec<u8, CAP, LenType> {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         let len = cmp::min(self.remaining_capacity(), data.len());
         let _result = self.try_extend_from_slice(&data[..len]);
@@ -1266,9 +1268,9 @@ impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 /// Requires crate feature `"serde"`
-impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> {
+impl<T: Serialize, const CAP: usize, LenType: LenUint> Serialize for ArrayVec<T, CAP, LenType> {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         where S: Serializer
     {
@@ -1276,19 +1278,19 @@ impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> {
     }
 }
 
-#[cfg(feature="serde")]
+#[cfg(feature = "serde")]
 /// Requires crate feature `"serde"`
-impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> {
+impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayVec<T, CAP, LenType> {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
         where D: Deserializer<'de>
     {
         use serde::de::{Visitor, SeqAccess, Error};
         use std::marker::PhantomData;
 
-        struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);
+        struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint>(PhantomData<(&'de (), [T; CAP], LenType)>);
 
-        impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> {
-            type Value = ArrayVec<T, CAP>;
+        impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Visitor<'de> for ArrayVecVisitor<'de, T, CAP, LenType> {
+            type Value = ArrayVec<T, CAP, LenType>;
 
             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                 write!(formatter, "an array with no more than {} items", CAP)
@@ -1297,7 +1299,7 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T
             fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
                 where SA: SeqAccess<'de>,
             {
-                let mut values = ArrayVec::<T, CAP>::new();
+                let mut values = ArrayVec::<T, CAP, LenType>::new();
 
                 while let Some(value) = seq.next_element()? {
                     if let Err(_) = values.try_push(value) {
@@ -1309,15 +1311,15 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T
             }
         }
 
-        deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP>(PhantomData))
+        deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP, LenType>(PhantomData))
     }
 }
 
 #[cfg(feature = "borsh")]
 /// Requires crate feature `"borsh"`
-impl<T, const CAP: usize> borsh::BorshSerialize for ArrayVec<T, CAP>
-where
-    T: borsh::BorshSerialize,
+impl<T, const CAP: usize, LenType: LenUint> borsh::BorshSerialize for ArrayVec<T, CAP, LenType>
+    where
+        T: borsh::BorshSerialize,
 {
     fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> {
         <[T] as borsh::BorshSerialize>::serialize(self.as_slice(), writer)
@@ -1326,9 +1328,9 @@ where
 
 #[cfg(feature = "borsh")]
 /// Requires crate feature `"borsh"`
-impl<T, const CAP: usize> borsh::BorshDeserialize for ArrayVec<T, CAP>
-where
-    T: borsh::BorshDeserialize,
+impl<T, const CAP: usize, LenType: LenUint> borsh::BorshDeserialize for ArrayVec<T, CAP, LenType>
+    where
+        T: borsh::BorshDeserialize,
 {
     fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> borsh::io::Result<Self> {
         let mut values = Self::new();
diff --git a/src/len_type.rs b/src/len_type.rs
new file mode 100644
index 0000000..f9dfe8c
--- /dev/null
+++ b/src/len_type.rs
@@ -0,0 +1,69 @@
+use core::ops::{Add, Sub};
+
+macro_rules! impl_lenuint {
+    ($Sealed:ty, $LenUint:ty, $ty: path) => {
+        impl $Sealed for $ty {}
+        impl $LenUint for $ty {
+            const MAX: usize = <$ty>::MAX as usize;
+            const ZERO: Self = 0;
+            fn from_usize(n: usize) -> Self { n as $ty }
+            fn to_usize(self) -> usize { self as usize }
+        }
+    };
+}
+
+macro_rules! impl_default_lentype_from_cap {
+    ($LenT:ty => $($CAP:literal),*) => {
+        $(
+            impl CapToDefaultLenType for ConstGenericSmuggler<$CAP> {
+                type T = $LenT;
+            }
+        )*
+    };
+}
+
+pub trait LenUint: Add + Sub + Copy + PartialOrd + PartialEq + private::Sealed  {
+    const MAX: usize;
+    const ZERO: Self;
+    fn from_usize(n: usize) -> Self;
+    fn to_usize(self) -> usize;
+}
+
+mod private {
+    pub trait Sealed {}
+
+    impl_lenuint!(Sealed, super::LenUint, u8);
+    impl_lenuint!(Sealed, super::LenUint, u16);
+    impl_lenuint!(Sealed, super::LenUint, u32);
+    #[cfg(target_pointer_width = "64")]
+    impl_lenuint!(Sealed, super::LenUint, u64);
+    impl_lenuint!(Sealed, super::LenUint, usize);
+}
+
+pub struct ConstGenericSmuggler<const CONST: usize> {}
+
+pub trait CapToDefaultLenType {
+    type T: LenUint;
+}
+
+impl_default_lentype_from_cap!(u8 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64, 100, 128, 200, 255);
+impl_default_lentype_from_cap!(u16 => 256, 500, 512, 1000, 1024, 2048, 4096, 8192, 16384, 32768, 65535);
+impl_default_lentype_from_cap!(u32 => 65536, 1000000, 4294967295);
+impl_default_lentype_from_cap!(u64 => 18446744073709551615);
+
+pub trait CapFitsInLenType {
+    const CHECK: ();
+}
+
+impl<LenType: LenUint, const CAP: usize> CapFitsInLenType for (ConstGenericSmuggler<CAP>, LenType) {
+    const CHECK: () = {
+        if CAP > LenType::MAX {
+            panic!("Cannot fit CAP into provided LenType");
+        }
+    };
+}
+
+pub type DefaultLenType<const CAP: usize> = <ConstGenericSmuggler<CAP> as CapToDefaultLenType>::T;
+pub const fn check_cap_fits_in_len_type<LenType: LenUint, const CAP: usize>() {
+    <(ConstGenericSmuggler<CAP>, LenType) as CapFitsInLenType>::CHECK
+}
diff --git a/src/lib.rs b/src/lib.rs
index f9a2fe6..9b6cbda 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -28,28 +28,7 @@ extern crate serde;
 #[cfg(not(feature="std"))]
 extern crate core as std;
 
-pub(crate) type LenUint = u32;
-
-macro_rules! assert_capacity_limit {
-    ($cap:expr) => {
-        if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() {
-            if $cap > LenUint::MAX as usize {
-                panic!("ArrayVec: largest supported capacity is u32::MAX")
-            }
-        }
-    }
-}
-
-macro_rules! assert_capacity_limit_const {
-    ($cap:expr) => {
-        if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() {
-            if $cap > LenUint::MAX as usize {
-                [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap]
-            }
-        }
-    }
-}
-
+mod len_type;
 mod arrayvec_impl;
 mod arrayvec;
 mod array_string;
@@ -59,5 +38,6 @@ mod utils;
 
 pub use crate::array_string::ArrayString;
 pub use crate::errors::CapacityError;
+pub use len_type::LenUint;
 
 pub use crate::arrayvec::{ArrayVec, IntoIter, Drain};
diff --git a/src/utils.rs b/src/utils.rs
index b8e5ddb..b425a51 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -8,4 +8,3 @@ impl<T, const N: usize> MakeMaybeUninit<T, N> {
 
     pub(crate) const ARRAY: [MaybeUninit<T>; N] = [Self::VALUE; N];
 }
-
diff --git a/tests/borsh.rs b/tests/borsh.rs
index f05abcf..0f31481 100644
--- a/tests/borsh.rs
+++ b/tests/borsh.rs
@@ -59,7 +59,7 @@ mod array_string {
 
     #[test]
     fn test_full() {
-        let string = ArrayString::from_byte_string(b"hello world").unwrap();
+        let string = ArrayString::<11>::from_byte_string(b"hello world").unwrap();
         assert_ser(&string, b"\x0b\0\0\0hello world");
         assert_roundtrip(&string);
     }
diff --git a/tests/tests.rs b/tests/tests.rs
index 2f8a5ef..ffd6729 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1,5 +1,6 @@
 extern crate arrayvec;
-#[macro_use] extern crate matches;
+#[macro_use]
+extern crate matches;
 
 use arrayvec::ArrayVec;
 use arrayvec::ArrayString;
@@ -13,7 +14,7 @@ use std::collections::HashMap;
 fn test_simple() {
     use std::ops::Add;
 
-    let mut vec: ArrayVec<Vec<i32>,  3> = ArrayVec::new();
+    let mut vec: ArrayVec<Vec<i32>, 3> = ArrayVec::new();
 
     vec.push(vec![1, 2, 3, 4]);
     vec.push(vec![10]);
@@ -29,7 +30,7 @@ fn test_simple() {
 
 #[test]
 fn test_capacity_left() {
-    let mut vec: ArrayVec<usize,  4> = ArrayVec::new();
+    let mut vec: ArrayVec<usize, 4> = ArrayVec::new();
     assert_eq!(vec.remaining_capacity(), 4);
     vec.push(1);
     assert_eq!(vec.remaining_capacity(), 3);
@@ -43,7 +44,7 @@ fn test_capacity_left() {
 
 #[test]
 fn test_extend_from_slice() {
-    let mut vec: ArrayVec<usize,  10> = ArrayVec::new();
+    let mut vec: ArrayVec<usize, 10> = ArrayVec::new();
 
     vec.try_extend_from_slice(&[1, 2, 3]).unwrap();
     assert_eq!(vec.len(), 3);
@@ -54,13 +55,13 @@ fn test_extend_from_slice() {
 
 #[test]
 fn test_extend_from_slice_error() {
-    let mut vec: ArrayVec<usize,  10> = ArrayVec::new();
+    let mut vec: ArrayVec<usize, 10> = ArrayVec::new();
 
     vec.try_extend_from_slice(&[1, 2, 3]).unwrap();
     let res = vec.try_extend_from_slice(&[0; 8]);
     assert_matches!(res, Err(_));
 
-    let mut vec: ArrayVec<usize,  0> = ArrayVec::new();
+    let mut vec: ArrayVec<usize, 0> = ArrayVec::new();
     let res = vec.try_extend_from_slice(&[0; 1]);
     assert_matches!(res, Err(_));
 }
@@ -70,14 +71,14 @@ fn test_try_from_slice_error() {
     use arrayvec::ArrayVec;
     use std::convert::TryInto as _;
 
-    let res: Result<ArrayVec<_,  2>, _> = (&[1, 2, 3] as &[_]).try_into();
+    let res: Result<ArrayVec<_, 2>, _> = (&[1, 2, 3] as &[_]).try_into();
     assert_matches!(res, Err(_));
 }
 
 #[test]
 fn test_u16_index() {
     const N: usize = 4096;
-    let mut vec: ArrayVec<_,  N> = ArrayVec::new();
+    let mut vec: ArrayVec<_, N> = ArrayVec::new();
     for _ in 0..N {
         assert!(vec.try_push(1u8).is_ok());
     }
@@ -87,7 +88,8 @@ fn test_u16_index() {
 
 #[test]
 fn test_iter() {
-    let mut iter = ArrayVec::from([1, 2, 3]).into_iter();
+    let vec: ArrayVec<_, 3> = ArrayVec::from([1, 2, 3]);
+    let mut iter = vec.into_iter();
     assert_eq!(iter.size_hint(), (3, Some(3)));
     assert_eq!(iter.next_back(), Some(3));
     assert_eq!(iter.next(), Some(1));
@@ -113,7 +115,7 @@ fn test_drop() {
     }
 
     {
-        let mut array = ArrayVec::<Bump,  128>::new();
+        let mut array = ArrayVec::<Bump, 128>::new();
         array.push(Bump(flag));
         array.push(Bump(flag));
     }
@@ -123,7 +125,7 @@ fn test_drop() {
     flag.set(0);
 
     {
-        let mut array = ArrayVec::<_,  3>::new();
+        let mut array = ArrayVec::<_, 3>::new();
         array.push(vec![Bump(flag)]);
         array.push(vec![Bump(flag), Bump(flag)]);
         array.push(vec![]);
@@ -142,7 +144,7 @@ fn test_drop() {
     // test into_inner
     flag.set(0);
     {
-        let mut array = ArrayVec::<_,  3>::new();
+        let mut array = ArrayVec::<_, 3>::new();
         array.push(Bump(flag));
         array.push(Bump(flag));
         array.push(Bump(flag));
@@ -156,7 +158,7 @@ fn test_drop() {
     // test take
     flag.set(0);
     {
-        let mut array1 = ArrayVec::<_,  3>::new();
+        let mut array1 = ArrayVec::<_, 3>::new();
         array1.push(Bump(flag));
         array1.push(Bump(flag));
         array1.push(Bump(flag));
@@ -171,7 +173,7 @@ fn test_drop() {
     // test cloning into_iter
     flag.set(0);
     {
-        let mut array = ArrayVec::<_,  3>::new();
+        let mut array = ArrayVec::<_, 3>::new();
         array.push(Bump(flag));
         array.push(Bump(flag));
         array.push(Bump(flag));
@@ -225,7 +227,7 @@ fn test_drop_panics() {
 
     flag.set(0);
     {
-        let mut array = ArrayVec::<Bump,  128>::new();
+        let mut array = ArrayVec::<Bump, 128>::new();
         array.push(Bump(flag));
         array.push(Bump(flag));
         array.push(Bump(flag));
@@ -241,7 +243,7 @@ fn test_drop_panics() {
 
     flag.set(0);
     {
-        let mut array = ArrayVec::<Bump,  16>::new();
+        let mut array = ArrayVec::<Bump, 16>::new();
         array.push(Bump(flag));
         array.push(Bump(flag));
         array.push(Bump(flag));
@@ -258,22 +260,20 @@ fn test_drop_panics() {
         // Check that all the tail elements drop, even if the first drop panics.
         assert_eq!(flag.get(), tail_len as i32);
     }
-
-
 }
 
 #[test]
 fn test_extend() {
     let mut range = 0..10;
 
-    let mut array: ArrayVec<_,  5> = range.by_ref().take(5).collect();
+    let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect();
     assert_eq!(&array[..], &[0, 1, 2, 3, 4]);
     assert_eq!(range.next(), Some(5));
 
     array.extend(range.by_ref().take(0));
     assert_eq!(range.next(), Some(6));
 
-    let mut array: ArrayVec<_,  10> = (0..3).collect();
+    let mut array: ArrayVec<_, 10> = (0..3).collect();
     assert_eq!(&array[..], &[0, 1, 2]);
     array.extend(3..5);
     assert_eq!(&array[..], &[0, 1, 2, 3, 4]);
@@ -284,7 +284,7 @@ fn test_extend() {
 fn test_extend_capacity_panic_1() {
     let mut range = 0..10;
 
-    let _: ArrayVec<_,  5> = range.by_ref().collect();
+    let _: ArrayVec<_, 5> = range.by_ref().collect();
 }
 
 #[should_panic]
@@ -292,7 +292,7 @@ fn test_extend_capacity_panic_1() {
 fn test_extend_capacity_panic_2() {
     let mut range = 0..10;
 
-    let mut array: ArrayVec<_,  5> = range.by_ref().take(5).collect();
+    let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect();
     assert_eq!(&array[..], &[0, 1, 2, 3, 4]);
     assert_eq!(range.next(), Some(5));
     array.extend(range.by_ref().take(1));
@@ -300,7 +300,7 @@ fn test_extend_capacity_panic_2() {
 
 #[test]
 fn test_is_send_sync() {
-    let data = ArrayVec::<Vec<i32>,  5>::new();
+    let data = ArrayVec::<Vec<i32>, 5>::new();
     &data as &dyn Send;
     &data as &dyn Sync;
 }
@@ -308,24 +308,24 @@ fn test_is_send_sync() {
 #[test]
 fn test_compact_size() {
     // 4 bytes + padding + length
-    type ByteArray = ArrayVec<u8,  4>;
+    type ByteArray = ArrayVec<u8, 4>;
     println!("{}", mem::size_of::<ByteArray>());
     assert!(mem::size_of::<ByteArray>() <= 2 * mem::size_of::<u32>());
 
     // just length
-    type EmptyArray = ArrayVec<u8,  0>;
+    type EmptyArray = ArrayVec<u8, 0>;
     println!("{}", mem::size_of::<EmptyArray>());
     assert!(mem::size_of::<EmptyArray>() <= mem::size_of::<u32>());
 
     // 3 elements + padding + length
-    type QuadArray = ArrayVec<u32,  3>;
+    type QuadArray = ArrayVec<u32, 3>;
     println!("{}", mem::size_of::<QuadArray>());
     assert!(mem::size_of::<QuadArray>() <= 4 * 4 + mem::size_of::<u32>());
 }
 
 #[test]
 fn test_still_works_with_option_arrayvec() {
-    type RefArray = ArrayVec<&'static i32,  2>;
+    type RefArray = ArrayVec<&'static i32, 2>;
     let array = Some(RefArray::new());
     assert!(array.is_some());
     println!("{:?}", array);
@@ -333,7 +333,7 @@ fn test_still_works_with_option_arrayvec() {
 
 #[test]
 fn test_drain() {
-    let mut v = ArrayVec::from([0; 8]);
+    let mut v: ArrayVec<i32, 8> = ArrayVec::from([0; 8]);
     v.pop();
     v.drain(0..7);
     assert_eq!(&v[..], &[]);
@@ -341,7 +341,7 @@ fn test_drain() {
     v.extend(0..8);
     v.drain(1..4);
     assert_eq!(&v[..], &[0, 4, 5, 6, 7]);
-    let u: ArrayVec<_,  3> = v.drain(1..4).rev().collect();
+    let u: ArrayVec<_, 3> = v.drain(1..4).rev().collect();
     assert_eq!(&u[..], &[6, 5, 4]);
     assert_eq!(&v[..], &[0, 7]);
     v.drain(..);
@@ -350,14 +350,14 @@ fn test_drain() {
 
 #[test]
 fn test_drain_range_inclusive() {
-    let mut v = ArrayVec::from([0; 8]);
+    let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]);
     v.drain(0..=7);
     assert_eq!(&v[..], &[]);
 
     v.extend(0..8);
     v.drain(1..=4);
     assert_eq!(&v[..], &[0, 5, 6, 7]);
-    let u: ArrayVec<_,  3> = v.drain(1..=2).rev().collect();
+    let u: ArrayVec<_, 3> = v.drain(1..=2).rev().collect();
     assert_eq!(&u[..], &[6, 5]);
     assert_eq!(&v[..], &[0, 7]);
     v.drain(..);
@@ -367,13 +367,13 @@ fn test_drain_range_inclusive() {
 #[test]
 #[should_panic]
 fn test_drain_range_inclusive_oob() {
-    let mut v = ArrayVec::from([0; 0]);
+    let mut v: ArrayVec<_, 0> = ArrayVec::from([0; 0]);
     v.drain(0..=0);
 }
 
 #[test]
 fn test_retain() {
-    let mut v = ArrayVec::from([0; 8]);
+    let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]);
     for (i, elt) in v.iter_mut().enumerate() {
         *elt = i;
     }
@@ -391,7 +391,7 @@ fn test_retain() {
 #[test]
 #[should_panic]
 fn test_drain_oob() {
-    let mut v = ArrayVec::from([0; 8]);
+    let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]);
     v.pop();
     v.drain(0..8);
 }
@@ -407,7 +407,7 @@ fn test_drop_panic() {
         }
     }
 
-    let mut array = ArrayVec::<DropPanic,  1>::new();
+    let mut array = ArrayVec::<DropPanic, 1>::new();
     array.push(DropPanic);
 }
 
@@ -422,17 +422,17 @@ fn test_drop_panic_into_iter() {
         }
     }
 
-    let mut array = ArrayVec::<DropPanic,  1>::new();
+    let mut array = ArrayVec::<DropPanic, 1>::new();
     array.push(DropPanic);
     array.into_iter();
 }
 
 #[test]
 fn test_insert() {
-    let mut v = ArrayVec::from([]);
+    let mut v: ArrayVec<_, 0> = ArrayVec::from([]);
     assert_matches!(v.try_push(1), Err(_));
 
-    let mut v = ArrayVec::<_,  3>::new();
+    let mut v = ArrayVec::<_, 3>::new();
     v.insert(0, 0);
     v.insert(1, 1);
     //let ret1 = v.try_insert(3, 3);
@@ -445,7 +445,7 @@ fn test_insert() {
     assert_eq!(&v[..], &[0, 1, 2]);
     assert_matches!(ret2, Err(_));
 
-    let mut v = ArrayVec::from([2]);
+    let mut v: ArrayVec<_, 1> = ArrayVec::from([2]);
     assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. }));
     assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. }));
     //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. }));
@@ -453,7 +453,7 @@ fn test_insert() {
 
 #[test]
 fn test_into_inner_1() {
-    let mut v = ArrayVec::from([1, 2]);
+    let mut v: ArrayVec<_, 2> = ArrayVec::from([1, 2]);
     v.pop();
     let u = v.clone();
     assert_eq!(v.into_inner(), Err(u));
@@ -461,7 +461,7 @@ fn test_into_inner_1() {
 
 #[test]
 fn test_into_inner_2() {
-    let mut v = ArrayVec::<String,  4>::new();
+    let mut v = ArrayVec::<String, 4>::new();
     v.push("a".into());
     v.push("b".into());
     v.push("c".into());
@@ -471,25 +471,25 @@ fn test_into_inner_2() {
 
 #[test]
 fn test_into_inner_3() {
-    let mut v = ArrayVec::<i32,  4>::new();
+    let mut v = ArrayVec::<i32, 4>::new();
     v.extend(1..=4);
     assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]);
 }
 
 #[test]
 fn test_take() {
-    let mut v1 = ArrayVec::<i32,  4>::new();
+    let mut v1 = ArrayVec::<i32, 4>::new();
     v1.extend(1..=4);
     let v2 = v1.take();
     assert!(v1.into_inner().is_err());
     assert_eq!(v2.into_inner().unwrap(), [1, 2, 3, 4]);
 }
 
-#[cfg(feature="std")]
+#[cfg(feature = "std")]
 #[test]
 fn test_write() {
     use std::io::Write;
-    let mut v = ArrayVec::<_,  8>::new();
+    let mut v = ArrayVec::<_, 8>::new();
     write!(&mut v, "\x01\x02\x03").unwrap();
     assert_eq!(&v[..], &[1, 2, 3]);
     let r = v.write(&[9; 16]).unwrap();
@@ -499,16 +499,16 @@ fn test_write() {
 
 #[test]
 fn array_clone_from() {
-    let mut v = ArrayVec::<_,  4>::new();
+    let mut v = ArrayVec::<_, 4>::new();
     v.push(vec![1, 2]);
     v.push(vec![3, 4, 5]);
     v.push(vec![6]);
     let reference = v.to_vec();
-    let mut u = ArrayVec::<_,  4>::new();
+    let mut u = ArrayVec::<_, 4>::new();
     u.clone_from(&v);
     assert_eq!(&u, &reference[..]);
 
-    let mut t = ArrayVec::<_,  4>::new();
+    let mut t = ArrayVec::<_, 4>::new();
     t.push(vec![97]);
     t.push(vec![]);
     t.push(vec![5, 6, 2]);
@@ -520,7 +520,7 @@ fn array_clone_from() {
     assert_eq!(&t, &reference[..]);
 }
 
-#[cfg(feature="std")]
+#[cfg(feature = "std")]
 #[test]
 fn test_string() {
     use std::error::Error;
@@ -557,7 +557,7 @@ fn test_string() {
 #[test]
 fn test_string_from() {
     let text = "hello world";
-	// Test `from` constructor
+    // Test `from` constructor
     let u = ArrayString::<11>::from(text).unwrap();
     assert_eq!(&u, text);
     assert_eq!(u.len(), text.len());
@@ -574,7 +574,7 @@ fn test_string_parse_from_str() {
 #[test]
 fn test_string_from_bytes() {
     let text = "hello world";
-    let u = ArrayString::from_byte_string(b"hello world").unwrap();
+    let u: ArrayString<11> = ArrayString::from_byte_string(b"hello world").unwrap();
     assert_eq!(&u, text);
     assert_eq!(u.len(), text.len());
 }
@@ -607,7 +607,7 @@ fn test_string_push() {
 
 #[test]
 fn test_insert_at_length() {
-    let mut v = ArrayVec::<_,  8>::new();
+    let mut v = ArrayVec::<_, 8>::new();
     let result1 = v.try_insert(0, "a");
     let result2 = v.try_insert(1, "b");
     assert!(result1.is_ok() && result2.is_ok());
@@ -617,7 +617,7 @@ fn test_insert_at_length() {
 #[should_panic]
 #[test]
 fn test_insert_out_of_bounds() {
-    let mut v = ArrayVec::<_,  8>::new();
+    let mut v = ArrayVec::<_, 8>::new();
     let _ = v.try_insert(1, "test");
 }
 
@@ -650,7 +650,7 @@ fn test_drop_in_insert() {
     flag.set(0);
 
     {
-        let mut array = ArrayVec::<_,  2>::new();
+        let mut array = ArrayVec::<_, 2>::new();
         array.push(Bump(flag));
         array.insert(0, Bump(flag));
         assert_eq!(flag.get(), 0);
@@ -665,7 +665,7 @@ fn test_drop_in_insert() {
 
 #[test]
 fn test_pop_at() {
-    let mut v = ArrayVec::<String,  4>::new();
+    let mut v = ArrayVec::<String, 4>::new();
     let s = String::from;
     v.push(s("a"));
     v.push(s("b"));
@@ -681,7 +681,7 @@ fn test_pop_at() {
 
 #[test]
 fn test_sizes() {
-    let v = ArrayVec::from([0u8; 1 << 16]);
+    let v: ArrayVec<_, { 1 << 16 }> = ArrayVec::from([0u8; 1 << 16]);
     assert_eq!(vec![0u8; v.len()], &v[..]);
 }
 
@@ -690,19 +690,19 @@ fn test_default() {
     use std::net;
     let s: ArrayString<4> = Default::default();
     // Something without `Default` implementation.
-    let v: ArrayVec<net::TcpStream,  4> = Default::default();
+    let v: ArrayVec<net::TcpStream, 4> = Default::default();
     assert_eq!(s.len(), 0);
     assert_eq!(v.len(), 0);
 }
 
-#[cfg(feature="array-sizes-33-128")]
+#[cfg(feature = "array-sizes-33-128")]
 #[test]
 fn test_sizes_33_128() {
     ArrayVec::from([0u8; 52]);
     ArrayVec::from([0u8; 127]);
 }
 
-#[cfg(feature="array-sizes-129-255")]
+#[cfg(feature = "array-sizes-129-255")]
 #[test]
 fn test_sizes_129_255() {
     ArrayVec::from([0u8; 237]);
@@ -715,14 +715,14 @@ fn test_extend_zst() {
     #[derive(Copy, Clone, PartialEq, Debug)]
     struct Z; // Zero sized type
 
-    let mut array: ArrayVec<_,  5> = range.by_ref().take(5).map(|_| Z).collect();
+    let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect();
     assert_eq!(&array[..], &[Z; 5]);
     assert_eq!(range.next(), Some(5));
 
     array.extend(range.by_ref().take(0).map(|_| Z));
     assert_eq!(range.next(), Some(6));
 
-    let mut array: ArrayVec<_,  10> = (0..3).map(|_| Z).collect();
+    let mut array: ArrayVec<_, 10> = (0..3).map(|_| Z).collect();
     assert_eq!(&array[..], &[Z; 3]);
     array.extend((3..5).map(|_| Z));
     assert_eq!(&array[..], &[Z; 5]);
@@ -736,32 +736,6 @@ fn test_try_from_argument() {
     assert_eq!(&v, "Hello 123");
 }
 
-#[test]
-fn allow_max_capacity_arrayvec_type() {
-    // this type is allowed to be used (but can't be constructed)
-    let _v: ArrayVec<(), {usize::MAX}>;
-}
-
-#[should_panic(expected="largest supported capacity")]
-#[test]
-fn deny_max_capacity_arrayvec_value() {
-    if mem::size_of::<usize>() <= mem::size_of::<u32>() {
-        panic!("This test does not work on this platform. 'largest supported capacity'");
-    }
-    // this type is allowed to be used (but can't be constructed)
-    let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new();
-}
-
-#[should_panic(expected="index out of bounds")]
-#[test]
-fn deny_max_capacity_arrayvec_value_const() {
-    if mem::size_of::<usize>() <= mem::size_of::<u32>() {
-        panic!("This test does not work on this platform. 'index out of bounds'");
-    }
-    // this type is allowed to be used (but can't be constructed)
-    let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const();
-}
-
 #[test]
 fn test_arrayvec_const_constructible() {
     const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new_const();