aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-06 17:52:16 -0400
committerBrian Cully <bjc@kublai.com>2019-08-06 17:52:35 -0400
commitd213bba502043aac09a0bdb845278a53ea04f600 (patch)
treea6ba6c1e46e56af1fd557c6476f01ef8321ef1d8
parent392239c7f522acb7ca5847a48dd9ab2480242924 (diff)
downloadclint-stable-support.tar.gz
clint-stable-support.zip
WIP: stalled out trying to implement const-fn feature.stable-support
Unfortunately, to maintain API compatibility, `replace` needs to be a regular borrow, so we need interior mutability with `UnsafeCell`. Simultaneously, `HandlerArray` needs to be `const fn` so it can be used where `lazy_static` isn't available, which means it needs to initialize its array in one go without the help of `MaybeUninit`. To do that, `Handler` must be `Copy`, but since it contains an `UnsafeCell` now, it cannot be copy. And thus we are boned. There are times when I think the premise of rust is admirable, but implementation is impossible.
-rw-r--r--src/fnnop.rs3
-rw-r--r--src/handler.rs27
-rw-r--r--src/lib.rs4
3 files changed, 28 insertions, 6 deletions
diff --git a/src/fnnop.rs b/src/fnnop.rs
index 871a6ab..13b9379 100644
--- a/src/fnnop.rs
+++ b/src/fnnop.rs
@@ -2,6 +2,7 @@
//
//#![feature(unboxed_closures)]
//#![feature(fn_traits)]
+use core::cell::UnsafeCell;
pub struct FnNOP();
@@ -16,4 +17,4 @@ impl FnOnce<()> for FnNOP {
extern "rust-call" fn call_once(self, _args: ()) {}
}
-static mut NOP: FnNOP = FnNOP();
+pub static mut NOP: UnsafeCell<FnNOP> = UnsafeCell::new(FnNOP());
diff --git a/src/handler.rs b/src/handler.rs
index 1087b21..ca8aea6 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -85,7 +85,9 @@
//! unsafe { SYSTICK_HANDLER.call() };
//! }
//! ```
-#[cfg(not(feature = "const-fn"))]
+#[cfg(feature = "const-fn")]
+use crate::fnnop::NOP;
+
use core::cell::UnsafeCell;
#[cfg(not(feature = "const-fn"))]
use core::ptr::NonNull;
@@ -93,7 +95,7 @@ use core::ptr::NonNull;
#[cfg(feature = "const-fn")]
pub struct Handler<'a> {
// Handler that will be executed on `call`.
- h: *mut dyn FnMut(),
+ h: UnsafeCell<*mut dyn FnMut()>,
lifetime: core::marker::PhantomData<&'a dyn FnMut()>,
}
#[cfg(not(feature = "const-fn"))]
@@ -108,7 +110,7 @@ impl<'a> Handler<'a> {
#[cfg(feature = "const-fn")]
pub const fn new() -> Self {
Self {
- h: &Self::default_handler,
+ h: UnsafeCell::new(unsafe { NOP.get() }),
lifetime: core::marker::PhantomData,
}
}
@@ -130,7 +132,7 @@ impl<'a> Handler<'a> {
pub unsafe fn replace(&self, f: &mut (dyn FnMut() + Send + 'a)) {
#[cfg(feature = "const-fn")]
{
- self.h = core::mem::transmute::<_, &'a _>(f);
+ *self.h.get() = core::mem::transmute::<_, &'a mut _>(f);
}
#[cfg(not(feature = "const-fn"))]
{
@@ -150,7 +152,7 @@ impl<'a> Handler<'a> {
pub unsafe fn call(&self) {
#[cfg(feature = "const-fn")]
{
- let f: &mut dyn FnMut() = &mut *(self.h as *mut dyn FnMut());
+ let f: &mut dyn FnMut() = &mut **self.h.get();
f();
}
#[cfg(not(feature = "const-fn"))]
@@ -167,6 +169,13 @@ impl<'a> Handler<'a> {
}
impl<'a> core::fmt::Debug for Handler<'a> {
+ #[cfg(feature = "const-fn")]
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ let (f0, f1) = unsafe { core::mem::transmute::<_, (usize, usize)>(*self.h.get()) };
+ write!(f, "Handler{{ h: (0x{:x}, 0x{:x}) }}", f0, f1)
+ }
+
+ #[cfg(not(feature = "const-fn"))]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let (f0, f1) = unsafe { core::mem::transmute::<_, (usize, usize)>(*self.h.get()) };
write!(f, "Handler{{ h: (0x{:x}, 0x{:x}) }}", f0, f1)
@@ -174,6 +183,14 @@ impl<'a> core::fmt::Debug for Handler<'a> {
}
unsafe impl Sync for Handler<'_> {}
+#[cfg(feature = "const-fn")]
+impl Copy for Handler<'_> {}
+#[cfg(feature = "const-fn")]
+impl Clone for Handler<'_> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
#[cfg(test)]
mod test {
diff --git a/src/lib.rs b/src/lib.rs
index d0ddad5..4ae3fd1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,9 +16,13 @@
#![no_std]
#![cfg_attr(feature = "const-fn", feature(const_fn))]
+#![cfg_attr(feature = "const-fn", feature(fn_traits))]
+#![cfg_attr(feature = "const-fn", feature(unboxed_closures))]
pub mod array;
pub mod cs;
+#[cfg(feature = "const-fn")]
+mod fnnop;
pub mod handler;
pub use array::HandlerArray;