diff --git a/Cargo.toml b/Cargo.toml index b18ea9e..6f96dd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ tinyvec_macros = { version = "0.1", optional = true } serde = { version = "1.0", optional = true, default-features = false } # Provides derived `Arbitrary` implementations arbitrary = { version = "1", optional = true } +# Detects the available `rustc` version +rustversion = "1.0.7" [features] default = [] @@ -29,17 +31,20 @@ std = ["alloc"] # "active" portion of an `ArrayVec` or `SliceVec`. grab_spare_slice = [] -# features that require rustc 1.40 +# formerly enabled features that require rustc 1.40 # use Vec::append if possible in TinyVec::append - 1.37 # DoubleEndedIterator::nth_back - 1.40 +# now these are automatically enabled if the listed rustc versions are detected rustc_1_40 = [] -# features that require rustc 1.55 +# formerly enabled features that require rustc 1.55 # use const generics to implement Array for all array lengths +# now that is automatically enabled if rustc 1.55+ is detected rustc_1_55 = ["rustc_1_40"] -# features that require rustc 1.57 +# formerly enabled features that require rustc 1.57 # add try_reserve functions to types that heap allocate. +# now that is automatically enabled if rustc 1.57+ is detected rustc_1_57 = ["rustc_1_55"] # allow use of nightly feature `slice_partition_dedup`, diff --git a/gen-array-impls.sh b/gen-array-impls.sh index 5db5cd7..4139e55 100755 --- a/gen-array-impls.sh +++ b/gen-array-impls.sh @@ -3,6 +3,7 @@ gen_impl() { local len=$1 cat <<-END + #[rustversion::before(1.55)] impl Array for [T; $len] { type Item = T; const CAPACITY: usize = $len; @@ -43,6 +44,7 @@ cat <<-END // ./gen-array-impls.sh > src/array/generated_impl.rs // from the repo root + #[rustversion::before(1.55)] use super::Array; $(for ((i = 0; i <= 33; i++)); do gen_impl $i; done) diff --git a/src-backup/arrayset.rs b/src-backup/arrayset.rs index 98e53f7..ca96da6 100644 --- a/src-backup/arrayset.rs +++ b/src-backup/arrayset.rs @@ -14,7 +14,8 @@ use core::{ #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct InsertError; -// TODO(when std): impl std::error::Error for InsertError {} +#[cfg(feature = "std")] +impl std::error::Error for InsertError {} impl fmt::Display for InsertError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/array.rs b/src/array.rs index 9a20984..e70767c 100644 --- a/src/array.rs +++ b/src/array.rs @@ -8,9 +8,10 @@ /// /// You are generally **not** expected to need to implement this yourself. It is /// already implemented for all the major array lengths (`0..=32` and the powers -/// of 2 up to 4,096), or for all array lengths with the feature `rustc_1_55`. +/// of 2 up to 4,096), or for all array lengths in Rust versions 1.55 and newer. /// -/// **Additional lengths can easily be added upon request.** +/// **Additional lengths can easily be added upon request for Rust 1.54 and +/// older.** /// /// ## Safety Reminder /// @@ -41,8 +42,12 @@ pub trait Array { fn default() -> Self; } -#[cfg(feature = "rustc_1_55")] +// These `*_impl` modules implement `Array` for primitive arrays. +// +// NOTE(2022-07-09): The `#[rustversion::...]` conditional compilation +// attributes are placed on the individual implementation blocks rather than on +// the modules because using procedural attribute macros on non-inline modules +// is unstable. Even if doing so becomes stable, it would be incompatible with +// `tinyvec`'s MSRV. mod const_generic_impl; - -#[cfg(not(feature = "rustc_1_55"))] mod generated_impl; diff --git a/src/array/const_generic_impl.rs b/src/array/const_generic_impl.rs index 2d9f1b1..695811d 100644 --- a/src/array/const_generic_impl.rs +++ b/src/array/const_generic_impl.rs @@ -1,5 +1,7 @@ +#[rustversion::since(1.55)] use super::Array; +#[rustversion::since(1.55)] impl Array for [T; N] { type Item = T; const CAPACITY: usize = N; diff --git a/src/array/generated_impl.rs b/src/array/generated_impl.rs index e7979ac..5dea235 100644 --- a/src/array/generated_impl.rs +++ b/src/array/generated_impl.rs @@ -2,8 +2,10 @@ // ./gen-array-impls.sh > src/array/generated_impl.rs // from the repo root +#[rustversion::before(1.55)] use super::Array; +#[rustversion::before(1.55)] impl Array for [T; 0] { type Item = T; const CAPACITY: usize = 0; @@ -26,6 +28,7 @@ impl Array for [T; 0] { } } +#[rustversion::before(1.55)] impl Array for [T; 1] { type Item = T; const CAPACITY: usize = 1; @@ -48,6 +51,7 @@ impl Array for [T; 1] { } } +#[rustversion::before(1.55)] impl Array for [T; 2] { type Item = T; const CAPACITY: usize = 2; @@ -70,6 +74,7 @@ impl Array for [T; 2] { } } +#[rustversion::before(1.55)] impl Array for [T; 3] { type Item = T; const CAPACITY: usize = 3; @@ -92,6 +97,7 @@ impl Array for [T; 3] { } } +#[rustversion::before(1.55)] impl Array for [T; 4] { type Item = T; const CAPACITY: usize = 4; @@ -114,6 +120,7 @@ impl Array for [T; 4] { } } +#[rustversion::before(1.55)] impl Array for [T; 5] { type Item = T; const CAPACITY: usize = 5; @@ -136,6 +143,7 @@ impl Array for [T; 5] { } } +#[rustversion::before(1.55)] impl Array for [T; 6] { type Item = T; const CAPACITY: usize = 6; @@ -165,6 +173,7 @@ impl Array for [T; 6] { } } +#[rustversion::before(1.55)] impl Array for [T; 7] { type Item = T; const CAPACITY: usize = 7; @@ -195,6 +204,7 @@ impl Array for [T; 7] { } } +#[rustversion::before(1.55)] impl Array for [T; 8] { type Item = T; const CAPACITY: usize = 8; @@ -226,6 +236,7 @@ impl Array for [T; 8] { } } +#[rustversion::before(1.55)] impl Array for [T; 9] { type Item = T; const CAPACITY: usize = 9; @@ -258,6 +269,7 @@ impl Array for [T; 9] { } } +#[rustversion::before(1.55)] impl Array for [T; 10] { type Item = T; const CAPACITY: usize = 10; @@ -291,6 +303,7 @@ impl Array for [T; 10] { } } +#[rustversion::before(1.55)] impl Array for [T; 11] { type Item = T; const CAPACITY: usize = 11; @@ -325,6 +338,7 @@ impl Array for [T; 11] { } } +#[rustversion::before(1.55)] impl Array for [T; 12] { type Item = T; const CAPACITY: usize = 12; @@ -360,6 +374,7 @@ impl Array for [T; 12] { } } +#[rustversion::before(1.55)] impl Array for [T; 13] { type Item = T; const CAPACITY: usize = 13; @@ -396,6 +411,7 @@ impl Array for [T; 13] { } } +#[rustversion::before(1.55)] impl Array for [T; 14] { type Item = T; const CAPACITY: usize = 14; @@ -433,6 +449,7 @@ impl Array for [T; 14] { } } +#[rustversion::before(1.55)] impl Array for [T; 15] { type Item = T; const CAPACITY: usize = 15; @@ -471,6 +488,7 @@ impl Array for [T; 15] { } } +#[rustversion::before(1.55)] impl Array for [T; 16] { type Item = T; const CAPACITY: usize = 16; @@ -510,6 +528,7 @@ impl Array for [T; 16] { } } +#[rustversion::before(1.55)] impl Array for [T; 17] { type Item = T; const CAPACITY: usize = 17; @@ -550,6 +569,7 @@ impl Array for [T; 17] { } } +#[rustversion::before(1.55)] impl Array for [T; 18] { type Item = T; const CAPACITY: usize = 18; @@ -591,6 +611,7 @@ impl Array for [T; 18] { } } +#[rustversion::before(1.55)] impl Array for [T; 19] { type Item = T; const CAPACITY: usize = 19; @@ -633,6 +654,7 @@ impl Array for [T; 19] { } } +#[rustversion::before(1.55)] impl Array for [T; 20] { type Item = T; const CAPACITY: usize = 20; @@ -676,6 +698,7 @@ impl Array for [T; 20] { } } +#[rustversion::before(1.55)] impl Array for [T; 21] { type Item = T; const CAPACITY: usize = 21; @@ -720,6 +743,7 @@ impl Array for [T; 21] { } } +#[rustversion::before(1.55)] impl Array for [T; 22] { type Item = T; const CAPACITY: usize = 22; @@ -765,6 +789,7 @@ impl Array for [T; 22] { } } +#[rustversion::before(1.55)] impl Array for [T; 23] { type Item = T; const CAPACITY: usize = 23; @@ -811,6 +836,7 @@ impl Array for [T; 23] { } } +#[rustversion::before(1.55)] impl Array for [T; 24] { type Item = T; const CAPACITY: usize = 24; @@ -858,6 +884,7 @@ impl Array for [T; 24] { } } +#[rustversion::before(1.55)] impl Array for [T; 25] { type Item = T; const CAPACITY: usize = 25; @@ -906,6 +933,7 @@ impl Array for [T; 25] { } } +#[rustversion::before(1.55)] impl Array for [T; 26] { type Item = T; const CAPACITY: usize = 26; @@ -955,6 +983,7 @@ impl Array for [T; 26] { } } +#[rustversion::before(1.55)] impl Array for [T; 27] { type Item = T; const CAPACITY: usize = 27; @@ -1005,6 +1034,7 @@ impl Array for [T; 27] { } } +#[rustversion::before(1.55)] impl Array for [T; 28] { type Item = T; const CAPACITY: usize = 28; @@ -1056,6 +1086,7 @@ impl Array for [T; 28] { } } +#[rustversion::before(1.55)] impl Array for [T; 29] { type Item = T; const CAPACITY: usize = 29; @@ -1108,6 +1139,7 @@ impl Array for [T; 29] { } } +#[rustversion::before(1.55)] impl Array for [T; 30] { type Item = T; const CAPACITY: usize = 30; @@ -1161,6 +1193,7 @@ impl Array for [T; 30] { } } +#[rustversion::before(1.55)] impl Array for [T; 31] { type Item = T; const CAPACITY: usize = 31; @@ -1215,6 +1248,7 @@ impl Array for [T; 31] { } } +#[rustversion::before(1.55)] impl Array for [T; 32] { type Item = T; const CAPACITY: usize = 32; @@ -1270,6 +1304,7 @@ impl Array for [T; 32] { } } +#[rustversion::before(1.55)] impl Array for [T; 33] { type Item = T; const CAPACITY: usize = 33; @@ -1326,6 +1361,7 @@ impl Array for [T; 33] { } } +#[rustversion::before(1.55)] impl Array for [T; 64] { type Item = T; const CAPACITY: usize = 64; @@ -1413,6 +1449,7 @@ impl Array for [T; 64] { } } +#[rustversion::before(1.55)] impl Array for [T; 128] { type Item = T; const CAPACITY: usize = 128; @@ -1564,6 +1601,7 @@ impl Array for [T; 128] { } } +#[rustversion::before(1.55)] impl Array for [T; 256] { type Item = T; const CAPACITY: usize = 256; @@ -1843,6 +1881,7 @@ impl Array for [T; 256] { } } +#[rustversion::before(1.55)] impl Array for [T; 512] { type Item = T; const CAPACITY: usize = 512; @@ -2378,6 +2417,7 @@ impl Array for [T; 512] { } } +#[rustversion::before(1.55)] impl Array for [T; 1024] { type Item = T; const CAPACITY: usize = 1024; @@ -3425,6 +3465,7 @@ impl Array for [T; 1024] { } } +#[rustversion::before(1.55)] impl Array for [T; 2048] { type Item = T; const CAPACITY: usize = 2048; @@ -5496,6 +5537,7 @@ impl Array for [T; 2048] { } } +#[rustversion::before(1.55)] impl Array for [T; 4096] { type Item = T; const CAPACITY: usize = 4096; diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 42ed134..cdfaf69 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1398,7 +1398,7 @@ impl DoubleEndedIterator for ArrayVecIterator { self.tail -= 1; return Some(take(item)); } - #[cfg(feature = "rustc_1_40")] + #[rustversion::since(1.40)] #[inline] fn nth_back(&mut self, n: usize) -> Option { let base = self.base as usize; @@ -1753,7 +1753,8 @@ where #[cfg(feature = "alloc")] use alloc::vec::Vec; -#[cfg(all(feature = "alloc", feature = "rustc_1_57"))] +#[cfg(feature = "alloc")] +#[rustversion::since(1.57)] use alloc::collections::TryReserveError; #[cfg(feature = "alloc")] @@ -1790,7 +1791,7 @@ impl ArrayVec { /// assert_eq!(v, &[1, 2, 3]); /// assert_eq!(v.capacity(), 13); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_drain_to_vec_and_reserve( &mut self, n: usize, ) -> Result, TryReserveError> { @@ -1831,7 +1832,7 @@ impl ArrayVec { /// // Vec may reserve more than necessary in order to prevent more future allocations. /// assert!(v.capacity() >= 3); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_drain_to_vec(&mut self) -> Result, TryReserveError> { self.try_drain_to_vec_and_reserve(0) } diff --git a/src/arrayvec_drain.rs b/src/arrayvec_drain.rs index 8721b7e..42b0400 100644 --- a/src/arrayvec_drain.rs +++ b/src/arrayvec_drain.rs @@ -60,7 +60,7 @@ impl<'a, T: 'a + Default> DoubleEndedIterator for ArrayVecDrain<'a, T> { self.iter.next_back().map(take) } - #[cfg(feature = "rustc_1_40")] + #[rustversion::since(1.40)] fn nth_back(&mut self, n: usize) -> Option { self.iter.nth_back(n).map(take) } diff --git a/src/lib.rs b/src/lib.rs index 68a7036..a4c81be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,8 +36,6 @@ //! ## Other Features //! * `grab_spare_slice` lets you get access to the "inactive" portions of an //! ArrayVec. -//! * `rustc_1_40` makes the crate assume a minimum rust version of `1.40.0`, -//! which allows some better internal optimizations. //! * `serde` provides a `Serialize` and `Deserialize` implementation for //! [`TinyVec`] and [`ArrayVec`] types, provided the inner item also has an //! implementation. @@ -100,8 +98,33 @@ mod tinyvec; #[cfg(feature = "alloc")] pub use crate::tinyvec::*; -// TODO MSRV(1.40.0): Just call the normal `core::mem::take` -#[inline(always)] +#[rustversion::since(1.40)] +use core::mem::take; + +/// Reimplement `core::mem::take` for Rust versions that lack it. +#[rustversion::before(1.40)] +#[inline] fn take(from: &mut T) -> T { replace(from, T::default()) } + +#[cfg(feature = "rustc_1_57")] +#[rustversion::before(1.57)] +compile_error!( + "The crate feature `rustc_1_57` of `tinyvec` is enabled but the available \ + Rust version is older than 1.57." +); + +#[cfg(feature = "rustc_1_55")] +#[rustversion::before(1.55)] +compile_error!( + "The crate feature `rustc_1_55` of `tinyvec` is enabled but the available \ + Rust version is older than 1.55." +); + +#[cfg(feature = "rustc_1_40")] +#[rustversion::before(1.40)] +compile_error!( + "The crate feature `rustc_1_40` of `tinyvec` is enabled but the available \ + Rust version is older than 1.40." +); diff --git a/src/tinyvec.rs b/src/tinyvec.rs index df3c80e..3972047 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -6,7 +6,7 @@ use alloc::vec::{self, Vec}; use core::convert::TryFrom; use tinyvec_macros::impl_mirrored; -#[cfg(feature = "rustc_1_57")] +#[rustversion::since(1.57)] use alloc::collections::TryReserveError; #[cfg(feature = "serde")] @@ -317,7 +317,7 @@ impl TinyVec { /// assert_eq!(Ok(()), tv.try_move_to_the_heap()); /// assert!(tv.is_heap()); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_move_to_the_heap(&mut self) -> Result<(), TryReserveError> { let arr = match self { TinyVec::Heap(_) => return Ok(()), @@ -364,7 +364,7 @@ impl TinyVec { /// assert!(tv.is_heap()); /// assert!(tv.capacity() >= 35); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_move_to_the_heap_and_reserve( &mut self, n: usize, ) -> Result<(), TryReserveError> { @@ -418,7 +418,7 @@ impl TinyVec { /// assert!(tv.is_heap()); /// assert!(tv.capacity() >= 5); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_reserve(&mut self, n: usize) -> Result<(), TryReserveError> { let arr = match self { TinyVec::Heap(h) => return h.try_reserve(n), @@ -487,7 +487,7 @@ impl TinyVec { /// assert!(tv.is_heap()); /// assert!(tv.capacity() >= 5); /// ``` - #[cfg(feature = "rustc_1_57")] + #[rustversion::since(1.57)] pub fn try_reserve_exact(&mut self, n: usize) -> Result<(), TryReserveError> { let arr = match self { TinyVec::Heap(h) => return h.try_reserve_exact(n), @@ -530,7 +530,7 @@ impl TinyVec { impl TinyVec { /// Move all values from `other` into this vec. - #[cfg(feature = "rustc_1_40")] + #[rustversion::since(1.37)] #[inline] pub fn append(&mut self, other: &mut Self) { self.reserve(other.len()); @@ -544,7 +544,7 @@ impl TinyVec { } /// Move all values from `other` into this vec. - #[cfg(not(feature = "rustc_1_40"))] + #[rustversion::before(1.37)] #[inline] pub fn append(&mut self, other: &mut Self) { match other { @@ -1101,7 +1101,7 @@ impl<'p, A: Array> DoubleEndedIterator for TinyVecDrain<'p, A> { #[inline] fn next_back(self: &mut Self) -> Option; - #[cfg(feature = "rustc_1_40")] + #[rustversion::since(1.40)] #[inline] fn nth_back(self: &mut Self, n: usize) -> Option; } @@ -1380,7 +1380,7 @@ impl DoubleEndedIterator for TinyVecIterator { #[inline] fn next_back(self: &mut Self) -> Option; - #[cfg(feature = "rustc_1_40")] + #[rustversion::since(1.40)] #[inline] fn nth_back(self: &mut Self, n: usize) -> Option; } diff --git a/tests/arrayvec.rs b/tests/arrayvec.rs index ad21770..565a2b2 100644 --- a/tests/arrayvec.rs +++ b/tests/arrayvec.rs @@ -387,7 +387,7 @@ fn iter_last_nth() { } #[test] -#[cfg(feature = "rustc_1_40")] +#[rustversion::since(1.40)] fn reviter() { let mut av: ArrayVec<[i32; 10]> = Default::default(); av.push(1); diff --git a/tests/tinyvec.rs b/tests/tinyvec.rs index 32e2a01..c79ee5a 100644 --- a/tests/tinyvec.rs +++ b/tests/tinyvec.rs @@ -304,7 +304,7 @@ fn TinyVec_reserve() { assert!(tv.capacity() >= 10); } -#[cfg(feature = "rustc_1_57")] +#[rustversion::since(1.57)] #[test] fn TinyVec_try_reserve() { let mut tv: TinyVec<[i32; 4]> = Default::default(); @@ -336,7 +336,7 @@ fn TinyVec_reserve_exact() { assert!(tv.capacity() >= 10); } -#[cfg(feature = "rustc_1_57")] +#[rustversion::since(1.57)] #[test] fn TinyVec_try_reserve_exact() { let mut tv: TinyVec<[i32; 4]> = Default::default(); @@ -374,7 +374,7 @@ fn TinyVec_move_to_heap_and_shrink() { assert_eq!(tv.as_slice(), [1, 2, 3, 4]); } -#[cfg(feature = "rustc_1_57")] +#[rustversion::since(1.57)] #[test] fn TinyVec_try_move_to_heap_and_shrink() { let mut tv: TinyVec<[i32; 4]> = Default::default();