225: A fix that stops panics from the old MaybeUninit impl r=korken89 a=korken89

Sometimes when running in debug mode the current implementation of `MaybeUninit` would panic, an example can be found here: 2bb89427fa/examples/rtfm-uarte-interrupts/src/main.rs (L106)
On debug this line will always panic, on release all is fine.

The issue seemed to be the manual `MaybeUninit` implementation, so I have merged the two implementations together.
Please have a look and see if my fix is unsound (it does however work, but not sure on UB).

cc @japaric @TeXitoi 

Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
This commit is contained in:
bors[bot] 2019-10-23 20:28:50 +00:00 committed by GitHub
commit 34a2767bdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 22 additions and 59 deletions

View file

@ -5,6 +5,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Fixed
- Soundness issue in the `MaybeUninit` implementation
- Warning for deprecated `mem::uninitialized`
## [v0.4.3] - 2019-04-21
### Changed

View file

@ -41,7 +41,7 @@ A concurrency framework for building real time systems.
## Requirements
- Rust 1.31.0+
- Rust 1.36.0+
- Applications must be written using the 2018 edition.

View file

@ -39,7 +39,7 @@
## Требования
- Rust 1.31.0+
- Rust 1.36.0+
- Программы нужно писать используя 2018 edition.

View file

@ -1948,13 +1948,13 @@ fn pre_init(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::Toke
// these are `MaybeUninit` arrays
for task in ctxt.tasks.values() {
let inputs = &task.inputs;
exprs.push(quote!(#inputs.write(core::mem::uninitialized());))
exprs.push(quote!(#inputs.write(core::mem::MaybeUninit::uninit());))
}
#[cfg(feature = "timer-queue")]
for task in ctxt.tasks.values() {
let scheduleds = &task.scheduleds;
exprs.push(quote!(#scheduleds.write(core::mem::uninitialized());))
exprs.push(quote!(#scheduleds.write(core::mem::MaybeUninit::uninit());))
}
// these are `MaybeUninit` `ReadyQueue`s

View file

@ -1,7 +1,5 @@
//! IMPLEMENTATION DETAILS. DO NOT USE ANYTHING IN THIS MODULE
#[cfg(not(feature = "nightly"))]
use core::ptr;
use core::{cell::Cell, u8};
#[cfg(armv7m)]
@ -64,13 +62,11 @@ impl Priority {
}
}
#[cfg(feature = "nightly")]
pub struct MaybeUninit<T> {
// we newtype so the end-user doesn't need `#![feature(maybe_uninit)]` in their code
inner: core::mem::MaybeUninit<T>,
}
#[cfg(feature = "nightly")]
impl<T> MaybeUninit<T> {
pub const fn uninit() -> Self {
MaybeUninit {
@ -86,61 +82,23 @@ impl<T> MaybeUninit<T> {
self.inner.as_mut_ptr()
}
pub fn write(&mut self, value: T) -> &mut T {
self.inner.write(value)
}
}
#[cfg(not(feature = "nightly"))]
pub struct MaybeUninit<T> {
value: Option<T>,
}
#[cfg(not(feature = "nightly"))]
const MSG: &str =
"you have hit a bug (UB) in RTFM implementation; try enabling this crate 'nightly' feature";
#[cfg(not(feature = "nightly"))]
impl<T> MaybeUninit<T> {
pub const fn uninit() -> Self {
MaybeUninit { value: None }
}
pub fn as_ptr(&self) -> *const T {
if let Some(x) = self.value.as_ref() {
x
} else {
unreachable!(MSG)
}
}
pub fn as_mut_ptr(&mut self) -> *mut T {
if let Some(x) = self.value.as_mut() {
x
} else {
unreachable!(MSG)
}
}
pub unsafe fn get_ref(&self) -> &T {
if let Some(x) = self.value.as_ref() {
x
} else {
unreachable!(MSG)
}
&*self.inner.as_ptr()
}
pub unsafe fn get_mut(&mut self) -> &mut T {
if let Some(x) = self.value.as_mut() {
x
} else {
unreachable!(MSG)
}
&mut *self.inner.as_mut_ptr()
}
pub fn write(&mut self, val: T) {
// NOTE(volatile) we have observed UB when this uses a plain `ptr::write`
unsafe { ptr::write_volatile(&mut self.value, Some(val)) }
#[cfg(feature = "nightly")]
pub fn write(&mut self, value: T) -> &mut T {
self.inner.write(value)
}
#[cfg(not(feature = "nightly"))]
pub fn write(&mut self, value: T) -> &mut T {
self.inner = core::mem::MaybeUninit::new(value);
unsafe { self.get_mut() }
}
}

View file

@ -16,7 +16,7 @@
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! This crate is guaranteed to compile on stable Rust 1.31 (2018 edition) and up. It *might*
//! This crate is guaranteed to compile on stable Rust 1.36 (2018 edition) and up. It *might*
//! compile on older versions but that may change in any new patch release.
//!
//! # Semantic Versioning
@ -41,7 +41,7 @@
//! usage, runtime overhead and initialization overhead. This feature requires a nightly compiler
//! and may stop working at any time!
#![cfg_attr(feature = "nightly", feature(maybe_uninit))]
#![cfg_attr(feature = "nightly", feature(maybe_uninit_extra))]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]