From 45a8d4fbcda7aa66eed1bfe6a14abcbf1a2eeabd Mon Sep 17 00:00:00 2001 From: c74d <8573dd@gmail.com> Date: Sat, 9 Jul 2022 08:21:10 +0000 Subject: [PATCH 1/2] Use `rustversion` to detect available Rust version `tinyvec` currently uses crate features `rustc_1_40`, `rustc_1_55`, and `rustc_1_57` to enable functions and optimizations that require Rust versions higher than the library's base MSRV of 1.34.0. This patch replaces the uses of these crate features with dtolnay's macro `rustversion`, which automatically detects the version of `rustc` with which the code is being compiled, thus allowing the optimizations enabled by newer Rust versions to be applied regardless of whether a dependent requests any of the `rustc_*` crate features. This may be especially useful for dependents whose own MSRVs would bar them from using those crate features without gating them behind crate features of their own, potentially requiring a proliferation of such crate features through a dependency tree. I would have limited this patch to using `rustversion` to enable optimizations automatically and not to replace the use of the crate features to gate functions that require Rust versions newer than 1.34.0, because I thought that using `rustversion` rather than the crate features to gate such functions might have been undesirable because it would mean losing the "Available on crate feature xyz only" hints on Docs.rs, but I see that Docs.rs doesn't apply those hints to functions anyway, so no such hints are lost by switching the gating mechanism to `rustversion`. This patch further uses `rustversion` to add compilation errors in case one of the `rustc_*` crate features is requested and the available Rust version is too old, such that the `rustc_*` crate features now function simply as static assertions that the running `rustc` supports the indicated Rust version. This patch, of course, adds a dependency on `rustversion`, which becomes this library's only non-optional dependency. Its MSRV is 1.31.0 and so does not raise the MSRV of this library. If having a non-optional dependency is unacceptable, an alternative could be to have `rustversion` be an optional, on-by-default dependency and to rely on the `rustc_*` crate features as before if `rustversion` is disabled. Rather than #[rustversion::since(1.57)] the conditional compilation clauses would look like #[cfg(any(feature = "rustversion", feature = "rustc_1_57"))] #[cfg_attr(feature = "rustversion", rustversion::since(1.57))] which is verbose enough that I suspect that rejecting `rustversion` altogether would be preferred. I admit that I do not understand why the comment in `Cargo.toml` on the crate feature `rustc_1_40` seems to say that "us[ing] Vec::append if possible in TinyVec::append" and overriding `DoubleEndedIterator::nth_back` require Rust 1.37 and Rust 1.40 respectively, when the standard library documentation says that `Vec::append` and `DoubleEndedIterator::nth_back` were stabilized in Rust 1.4.0 and Rust 1.37.0 respectively. --- Cargo.toml | 11 ++++++--- gen-array-impls.sh | 2 ++ src/array.rs | 15 ++++++++---- src/array/const_generic_impl.rs | 2 ++ src/array/generated_impl.rs | 42 +++++++++++++++++++++++++++++++++ src/arrayvec.rs | 9 +++---- src/arrayvec_drain.rs | 2 +- src/lib.rs | 23 ++++++++++++++++-- src/tinyvec.rs | 18 +++++++------- tests/arrayvec.rs | 2 +- tests/tinyvec.rs | 6 ++--- 11 files changed, 104 insertions(+), 28 deletions(-) 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/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..cb84926 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. @@ -105,3 +103,24 @@ pub use crate::tinyvec::*; 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." +); \ No newline at end of file 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(); From 79f12c30264c9ac3f42228a9e8ac25690ab24bba Mon Sep 17 00:00:00 2001 From: c74d <8573dd@gmail.com> Date: Sat, 9 Jul 2022 11:49:48 +0000 Subject: [PATCH 2/2] Fix TODO items Implement two things that were tracked in TODO comments, although only one appears to be in live code: using `core::mem::take` rather than a reimplementation of it when Rust 1.40 is available. I changed the `#[inline(always)]` on the reimplemented `take` to `#[inline]` to match what `core` has, figuring that `core` would know best what level of inlining hint it should have. On the other hand, do `tinyvec`'s benchmarks indicate that `#[inline(always)]` helps? If so, I suppose reimplementing the function in all cases may be preferred, in which case this patch would be unnecessary. --- src-backup/arrayset.rs | 3 ++- src/lib.rs | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) 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/lib.rs b/src/lib.rs index cb84926..a4c81be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,8 +98,12 @@ 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()) } @@ -123,4 +127,4 @@ compile_error!( compile_error!( "The crate feature `rustc_1_40` of `tinyvec` is enabled but the available \ Rust version is older than 1.40." -); \ No newline at end of file +);