mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
Merge #225
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:
commit
34a2767bdf
6 changed files with 22 additions and 59 deletions
|
@ -5,6 +5,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Soundness issue in the `MaybeUninit` implementation
|
||||||
|
- Warning for deprecated `mem::uninitialized`
|
||||||
|
|
||||||
## [v0.4.3] - 2019-04-21
|
## [v0.4.3] - 2019-04-21
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -41,7 +41,7 @@ A concurrency framework for building real time systems.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Rust 1.31.0+
|
- Rust 1.36.0+
|
||||||
|
|
||||||
- Applications must be written using the 2018 edition.
|
- Applications must be written using the 2018 edition.
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
## Требования
|
## Требования
|
||||||
|
|
||||||
- Rust 1.31.0+
|
- Rust 1.36.0+
|
||||||
|
|
||||||
- Программы нужно писать используя 2018 edition.
|
- Программы нужно писать используя 2018 edition.
|
||||||
|
|
||||||
|
|
|
@ -1948,13 +1948,13 @@ fn pre_init(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::Toke
|
||||||
// these are `MaybeUninit` arrays
|
// these are `MaybeUninit` arrays
|
||||||
for task in ctxt.tasks.values() {
|
for task in ctxt.tasks.values() {
|
||||||
let inputs = &task.inputs;
|
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")]
|
#[cfg(feature = "timer-queue")]
|
||||||
for task in ctxt.tasks.values() {
|
for task in ctxt.tasks.values() {
|
||||||
let scheduleds = &task.scheduleds;
|
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
|
// these are `MaybeUninit` `ReadyQueue`s
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! IMPLEMENTATION DETAILS. DO NOT USE ANYTHING IN THIS MODULE
|
//! IMPLEMENTATION DETAILS. DO NOT USE ANYTHING IN THIS MODULE
|
||||||
|
|
||||||
#[cfg(not(feature = "nightly"))]
|
|
||||||
use core::ptr;
|
|
||||||
use core::{cell::Cell, u8};
|
use core::{cell::Cell, u8};
|
||||||
|
|
||||||
#[cfg(armv7m)]
|
#[cfg(armv7m)]
|
||||||
|
@ -64,13 +62,11 @@ impl Priority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub struct MaybeUninit<T> {
|
pub struct MaybeUninit<T> {
|
||||||
// we newtype so the end-user doesn't need `#![feature(maybe_uninit)]` in their code
|
// we newtype so the end-user doesn't need `#![feature(maybe_uninit)]` in their code
|
||||||
inner: core::mem::MaybeUninit<T>,
|
inner: core::mem::MaybeUninit<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
impl<T> MaybeUninit<T> {
|
impl<T> MaybeUninit<T> {
|
||||||
pub const fn uninit() -> Self {
|
pub const fn uninit() -> Self {
|
||||||
MaybeUninit {
|
MaybeUninit {
|
||||||
|
@ -86,61 +82,23 @@ impl<T> MaybeUninit<T> {
|
||||||
self.inner.as_mut_ptr()
|
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 {
|
pub unsafe fn get_ref(&self) -> &T {
|
||||||
if let Some(x) = self.value.as_ref() {
|
&*self.inner.as_ptr()
|
||||||
x
|
|
||||||
} else {
|
|
||||||
unreachable!(MSG)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_mut(&mut self) -> &mut T {
|
pub unsafe fn get_mut(&mut self) -> &mut T {
|
||||||
if let Some(x) = self.value.as_mut() {
|
&mut *self.inner.as_mut_ptr()
|
||||||
x
|
|
||||||
} else {
|
|
||||||
unreachable!(MSG)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&mut self, val: T) {
|
#[cfg(feature = "nightly")]
|
||||||
// NOTE(volatile) we have observed UB when this uses a plain `ptr::write`
|
pub fn write(&mut self, value: T) -> &mut T {
|
||||||
unsafe { ptr::write_volatile(&mut self.value, Some(val)) }
|
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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
//!
|
//!
|
||||||
//! # Minimum Supported Rust Version (MSRV)
|
//! # 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.
|
//! compile on older versions but that may change in any new patch release.
|
||||||
//!
|
//!
|
||||||
//! # Semantic Versioning
|
//! # Semantic Versioning
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
//! usage, runtime overhead and initialization overhead. This feature requires a nightly compiler
|
//! usage, runtime overhead and initialization overhead. This feature requires a nightly compiler
|
||||||
//! and may stop working at any time!
|
//! 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(missing_docs)]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
Loading…
Reference in a new issue