From b56c3b78d067ea761d3308d8e2aa2dbba4f0426b Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 10 Jul 2019 16:40:50 +0200 Subject: [PATCH 1/3] FEAT: Use stable MaybeUninit when we can (feature detected) --- build.rs | 21 +++++++++++++++----- src/lib.rs | 7 +++++-- src/maybe_uninit_stable.rs | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 src/maybe_uninit_stable.rs diff --git a/build.rs b/build.rs index 1a4ac7d..a91c5f4 100644 --- a/build.rs +++ b/build.rs @@ -11,17 +11,28 @@ fn main() { } fn detect_maybe_uninit() { + let has_stable_maybe_uninit = probe(&stable_maybe_uninit()); + if has_stable_maybe_uninit { + println!("cargo:rustc-cfg=has_stable_maybe_uninit"); + return; + } let has_unstable_union_with_md = probe(&maybe_uninit_code(true)); if has_unstable_union_with_md { println!("cargo:rustc-cfg=has_manually_drop_in_union"); println!("cargo:rustc-cfg=has_union_feature"); - return; } +} - let has_stable_union_with_md = probe(&maybe_uninit_code(false)); - if has_stable_union_with_md { - println!("cargo:rustc-cfg=has_manually_drop_in_union"); - } +// To guard against changes in this currently unstable feature, use +// a detection tests instead of a Rustc version and/or date test. +fn stable_maybe_uninit() -> String { + let code = " + #![allow(warnings)] + use std::mem::MaybeUninit; + + fn main() { } + "; + code.to_string() } // To guard against changes in this currently unstable feature, use diff --git a/src/lib.rs b/src/lib.rs index cd8f0b9..1e05e59 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,9 +50,12 @@ use std::fmt; use std::io; -#[cfg(has_manually_drop_in_union)] +#[cfg(has_stable_maybe_uninit)] +#[path="maybe_uninit_stable.rs"] mod maybe_uninit; -#[cfg(not(has_manually_drop_in_union))] +#[cfg(all(not(has_stable_maybe_uninit), has_manually_drop_in_union))] +mod maybe_uninit; +#[cfg(all(not(has_stable_maybe_uninit), not(has_manually_drop_in_union)))] #[path="maybe_uninit_nodrop.rs"] mod maybe_uninit; diff --git a/src/maybe_uninit_stable.rs b/src/maybe_uninit_stable.rs new file mode 100644 index 0000000..cb631a9 --- /dev/null +++ b/src/maybe_uninit_stable.rs @@ -0,0 +1,40 @@ + + +use array::Array; +use std::mem::MaybeUninit as StdMaybeUninit; + +pub struct MaybeUninit { + inner: StdMaybeUninit, +} + +impl MaybeUninit { + /// Create a new MaybeUninit with uninitialized interior + pub unsafe fn uninitialized() -> Self { + MaybeUninit { inner: StdMaybeUninit::uninit() } + } + + /// Create a new MaybeUninit from the value `v`. + pub fn from(v: T) -> Self { + MaybeUninit { inner: StdMaybeUninit::new(v) } + } + + // Raw pointer casts written so that we don't reference or access the + // uninitialized interior value + + /// Return a raw pointer to the start of the interior array + pub fn ptr(&self) -> *const T::Item + where T: Array + { + // std MaybeUninit creates a &self.value reference here which is + // not guaranteed to be sound in our case - we will partially + // initialize the value, not always wholly. + self.inner.as_ptr() as *const T::Item + } + + /// Return a mut raw pointer to the start of the interior array + pub fn ptr_mut(&mut self) -> *mut T::Item + where T: Array + { + self.inner.as_mut_ptr() as *mut T::Item + } +} From 93220e55ae1a20e6d65db1575635946c816ac351 Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 10 Jul 2019 16:57:48 +0200 Subject: [PATCH 2/3] TEST: Update tests for new MaybeUninit usage (Also remove the size check since we can't rely on it, even if we want to ensure it has no overhead for the bytes case.) --- .travis.yml | 5 +++-- tests/tests.rs | 8 +++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3730670..c02af70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ matrix: - rust: stable env: - FEATURES='array-sizes-33-128 array-sizes-129-255' + - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 - rust: beta - rust: nightly env: @@ -23,12 +24,12 @@ matrix: - rust: nightly env: - NODROP_FEATURES='use_needs_drop' - - ARRAYVECTEST_ENSURE_UNION=1 + - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 - rust: nightly env: - FEATURES='serde use_union' - NODROP_FEATURES='use_union' - - ARRAYVECTEST_ENSURE_UNION=1 + - ARRAYVECTEST_ENSURE_MAYBEUNINIT=1 branches: only: - master diff --git a/tests/tests.rs b/tests/tests.rs index 0e69467..b8dbadb 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -510,10 +510,8 @@ fn test_sizes_129_255() { #[test] -fn test_nightly_uses_maybe_uninit() { - if option_env!("ARRAYVECTEST_ENSURE_UNION").map(|s| !s.is_empty()).unwrap_or(false) { - assert!(cfg!(has_manually_drop_in_union)); - type ByteArray = ArrayVec<[u8; 4]>; - assert!(mem::size_of::() == 5); +fn test_newish_stable_uses_maybe_uninit() { + if option_env!("ARRAYVECTEST_ENSURE_MAYBEUNINIT").map(|s| !s.is_empty()).unwrap_or(false) { + assert!(cfg!(has_stable_maybe_uninit)); } } From 97925027920f7a284774f76a48c3126297d2fd13 Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 10 Jul 2019 17:23:34 +0200 Subject: [PATCH 3/3] 0.4.11 --- Cargo.toml | 2 +- README.rst | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4dd9697..0d1eb8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" authors = ["bluss"] license = "MIT/Apache-2.0" diff --git a/README.rst b/README.rst index 4af5330..6f6476f 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,13 @@ __ https://docs.rs/arrayvec Recent Changes (arrayvec) ------------------------- +- 0.4.11 + + - In Rust 1.36 or later, use newly stable MaybeUninit. This extends the + soundness work introduced in 0.4.9, we are finally able to use this in + stable. We use feature detection (build script) to enable this at build + time. + - 0.4.10 - Use ``repr(C)`` in the ``union`` version that was introduced in 0.4.9, to