Skip to content

Commit

Permalink
Merge pull request #127 from bluss/stable-maybe-uninit
Browse files Browse the repository at this point in the history
Use stable MaybeUninit when we can (feature detected)
  • Loading branch information
bluss authored Jul 10, 2019
2 parents 21661fa + 93220e5 commit c155b40
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 14 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down
21 changes: 16 additions & 5 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
40 changes: 40 additions & 0 deletions src/maybe_uninit_stable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@


use array::Array;
use std::mem::MaybeUninit as StdMaybeUninit;

pub struct MaybeUninit<T> {
inner: StdMaybeUninit<T>,
}

impl<T> MaybeUninit<T> {
/// 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
}
}
8 changes: 3 additions & 5 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<ByteArray>() == 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));
}
}

0 comments on commit c155b40

Please sign in to comment.