diff options
author | Brian Cully <bjc@kublai.com> | 2019-08-06 17:52:16 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2019-08-06 17:52:35 -0400 |
commit | d213bba502043aac09a0bdb845278a53ea04f600 (patch) | |
tree | a6ba6c1e46e56af1fd557c6476f01ef8321ef1d8 | |
parent | 392239c7f522acb7ca5847a48dd9ab2480242924 (diff) | |
download | clint-d213bba502043aac09a0bdb845278a53ea04f600.tar.gz clint-d213bba502043aac09a0bdb845278a53ea04f600.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.rs | 3 | ||||
-rw-r--r-- | src/handler.rs | 27 | ||||
-rw-r--r-- | src/lib.rs | 4 |
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 { @@ -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; |