From 0a8de1d40f3154133e3bc3cf779dfe9eee7a4cfa Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 2 Nov 2023 19:35:53 -0500 Subject: [PATCH] clean up ref mapping with GATs --- packages/generational-box/src/lib.rs | 81 ++++++++++----- packages/signals/src/effect.rs | 9 +- packages/signals/src/impls.rs | 100 ++++++++++-------- packages/signals/src/rt.rs | 57 +++++------ packages/signals/src/selector.rs | 3 +- packages/signals/src/signal.rs | 145 +++++++++++++++++++-------- 6 files changed, 245 insertions(+), 150 deletions(-) diff --git a/packages/generational-box/src/lib.rs b/packages/generational-box/src/lib.rs index ec1986f39..87941c99e 100644 --- a/packages/generational-box/src/lib.rs +++ b/packages/generational-box/src/lib.rs @@ -247,53 +247,82 @@ impl Default for SyncStorage { } } -pub trait Mappable: Deref { - type Mapped: Deref; +pub trait Mappable: Deref { + type Mapped: Mappable + Deref; - fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped; + fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped; + + fn try_map(_self: Self, f: fn(&T) -> Option<&U>) -> Option>; } -impl Mappable for Ref<'static, T> { - type Mapped = Ref<'static, U>; +impl Mappable for Ref<'static, T> { + type Mapped = Ref<'static, U>; - fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped { + fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped { Ref::map(_self, f) } + + fn try_map(_self: Self, f: fn(&T) -> Option<&U>) -> Option> { + Ref::try_map(_self, f) + } } -impl Mappable for MappedRwLockReadGuard<'static, T> { - type Mapped = MappedRwLockReadGuard<'static, U>; +impl Mappable for MappedRwLockReadGuard<'static, T> { + type Mapped = MappedRwLockReadGuard<'static, U>; - fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped { + fn map(_self: Self, f: fn(&T) -> &U) -> Self::Mapped { MappedRwLockReadGuard::map(_self, f) } -} -pub trait MappableMut: DerefMut { - type Mapped: DerefMut; - - fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped; -} - -impl MappableMut for RefMut<'static, T> { - type Mapped = RefMut<'static, U>; - - fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped { - RefMut::map(_self, f) + fn try_map(_self: Self, f: fn(&T) -> Option<&U>) -> Option> { + MappedRwLockReadGuard::try_map(_self, f).ok() } } -impl MappableMut for MappedRwLockWriteGuard<'static, T> { - type Mapped = MappedRwLockWriteGuard<'static, U>; +pub trait MappableMut: DerefMut { + type Mapped: MappableMut + DerefMut; - fn map(_self: Self, f: fn(&mut T) -> &mut U) -> Self::Mapped { + fn map(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped; + + fn try_map( + _self: Self, + f: impl FnOnce(&mut T) -> Option<&mut U>, + ) -> Option>; +} + +impl MappableMut for RefMut<'static, T> { + type Mapped = RefMut<'static, U>; + + fn map(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped { + RefMut::map(_self, f) + } + + fn try_map( + _self: Self, + f: impl FnOnce(&mut T) -> Option<&mut U>, + ) -> Option> { + RefMut::try_map(_self, f) + } +} + +impl MappableMut for MappedRwLockWriteGuard<'static, T> { + type Mapped = MappedRwLockWriteGuard<'static, U>; + + fn map(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped { MappedRwLockWriteGuard::map(_self, f) } + + fn try_map( + _self: Self, + f: impl FnOnce(&mut T) -> Option<&mut U>, + ) -> Option> { + MappedRwLockWriteGuard::try_map(_self, f).ok() + } } pub trait Storage: Copy + AnyStorage { - type Ref: Deref; - type Mut: DerefMut; + type Ref: Mappable + Deref; + type Mut: MappableMut + DerefMut; fn try_read(&self) -> Option; fn read(&self) -> Self::Ref { diff --git a/packages/signals/src/effect.rs b/packages/signals/src/effect.rs index 2ab29780d..9d6231eb3 100644 --- a/packages/signals/src/effect.rs +++ b/packages/signals/src/effect.rs @@ -1,15 +1,14 @@ use core::{self, fmt::Debug}; -use std::fmt::{self, Formatter}; -// use dioxus_core::prelude::*; -use generational_box::SyncStorage; +use generational_box::UnsyncStorage; +use std::fmt::{self, Formatter}; use crate::use_signal; use crate::{dependency::Dependency, CopyValue}; #[derive(Copy, Clone, PartialEq)] pub(crate) struct EffectStack { - pub(crate) effects: CopyValue, SyncStorage>, + pub(crate) effects: CopyValue, UnsyncStorage>, } impl Default for EffectStack { @@ -69,7 +68,7 @@ pub fn use_effect_with_dependencies( #[derive(Copy, Clone, PartialEq)] pub struct Effect { pub(crate) source: ScopeId, - pub(crate) callback: CopyValue, SyncStorage>, + pub(crate) callback: CopyValue, UnsyncStorage>, pub(crate) effect_stack: EffectStack, } diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index e97ebc452..a217dfaa4 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -1,6 +1,7 @@ use crate::rt::CopyValue; use crate::signal::{ReadOnlySignal, Signal, Write}; use crate::SignalData; +use generational_box::Mappable; use generational_box::{MappableMut, Storage}; use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard}; @@ -11,40 +12,40 @@ use std::{ macro_rules! read_impls { ($ty:ident) => { - impl Default for $ty { + impl> Default for $ty { fn default() -> Self { Self::new(Default::default()) } } - impl std::clone::Clone for $ty { + impl> std::clone::Clone for $ty { fn clone(&self) -> Self { *self } } - impl Copy for $ty {} + impl + Copy> Copy for $ty {} - impl Display for $ty { + impl> Display for $ty { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Display::fmt(v, f)) } } - impl Debug for $ty { + impl> Debug for $ty { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.with(|v| Debug::fmt(v, f)) } } - impl $ty> { + impl> $ty, S> { /// Read a value from the inner vector. pub fn get(&self, index: usize) -> Option> { MappedRwLockReadGuard::try_map(self.read(), |v| v.get(index)).ok() } } - impl $ty> { + impl> $ty, S> { /// Unwraps the inner value and clones it. pub fn unwrap(&self) -> T where @@ -63,7 +64,7 @@ macro_rules! read_impls { macro_rules! write_impls { ($ty:ident) => { - impl + Copy + 'static> std::ops::Add for $ty { + impl + Copy + 'static, S: Storage> std::ops::Add for $ty { type Output = T; fn add(self, rhs: T) -> Self::Output { @@ -71,19 +72,23 @@ macro_rules! write_impls { } } - impl + Copy + 'static> std::ops::AddAssign for $ty { + impl + Copy + 'static, S: Storage> std::ops::AddAssign + for $ty + { fn add_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v + rhs) } } - impl + Copy + 'static> std::ops::SubAssign for $ty { + impl + Copy + 'static, S: Storage> std::ops::SubAssign + for $ty + { fn sub_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v - rhs) } } - impl + Copy + 'static> std::ops::Sub for $ty { + impl + Copy + 'static, S: Storage> std::ops::Sub for $ty { type Output = T; fn sub(self, rhs: T) -> Self::Output { @@ -91,13 +96,15 @@ macro_rules! write_impls { } } - impl + Copy + 'static> std::ops::MulAssign for $ty { + impl + Copy + 'static, S: Storage> std::ops::MulAssign + for $ty + { fn mul_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v * rhs) } } - impl + Copy + 'static> std::ops::Mul for $ty { + impl + Copy + 'static, S: Storage> std::ops::Mul for $ty { type Output = T; fn mul(self, rhs: T) -> Self::Output { @@ -105,13 +112,15 @@ macro_rules! write_impls { } } - impl + Copy + 'static> std::ops::DivAssign for $ty { + impl + Copy + 'static, S: Storage> std::ops::DivAssign + for $ty + { fn div_assign(&mut self, rhs: T) { self.with_mut(|v| *v = *v / rhs) } } - impl + Copy + 'static> std::ops::Div for $ty { + impl + Copy + 'static, S: Storage> std::ops::Div for $ty { type Output = T; fn div(self, rhs: T) -> Self::Output { @@ -119,7 +128,7 @@ macro_rules! write_impls { } } - impl $ty> { + impl> $ty, S> { /// Pushes a new value to the end of the vector. pub fn push(&self, value: T) { self.with_mut(|v| v.push(value)) @@ -171,7 +180,7 @@ macro_rules! write_impls { } } - impl $ty> { + impl> $ty, S> { /// Takes the value out of the Option. pub fn take(&self) -> Option { self.with_mut(|v| v.take()) @@ -183,7 +192,7 @@ macro_rules! write_impls { } /// Gets the value out of the Option, or inserts the given value if the Option is empty. - pub fn get_or_insert(&self, default: T) -> MappedRwLockReadGuard<'_, T> { + pub fn get_or_insert(&self, default: T) -> S::Ref { self.get_or_insert_with(|| default) } @@ -191,25 +200,25 @@ macro_rules! write_impls { pub fn get_or_insert_with( &self, default: impl FnOnce() -> T, - ) -> MappedRwLockReadGuard<'_, T> { + ) -> >::Mapped { let borrow = self.read(); if borrow.is_none() { drop(borrow); self.with_mut(|v| *v = Some(default())); - MappedRwLockReadGuard::map(self.read(), |v| v.as_ref().unwrap()) + S::Ref::map(self.read(), |v| v.as_ref().unwrap()) } else { - MappedRwLockReadGuard::map(borrow, |v| v.as_ref().unwrap()) + S::Ref::map(borrow, |v| v.as_ref().unwrap()) } } } }; } -// read_impls!(CopyValue); -// write_impls!(CopyValue); -// read_impls!(Signal); -// write_impls!(Signal); -// read_impls!(ReadOnlySignal); +read_impls!(CopyValue); +write_impls!(CopyValue); +read_impls!(Signal); +write_impls!(Signal); +read_impls!(ReadOnlySignal); /// An iterator over the values of a `CopyValue>`. pub struct CopyValueIterator> { @@ -240,23 +249,19 @@ impl> IntoIterator for CopyValue, S> { } } -impl>> CopyValue, S> -where - >>::Mut: MappableMut, T>, -{ +impl>> CopyValue, S> { /// Write to an element in the inner vector. - pub fn get_mut(&self, index: usize) -> Option<, T>>::Mapped> { - MappedRwLockWriteGuard::try_map(self.write(), |v| v.get_mut(index)).ok() + pub fn get_mut(&self, index: usize) -> Option<>>::Mapped> { + S::Mut::try_map(self.write(), |v: &mut Vec| v.get_mut(index)) } } -impl>> CopyValue, S> -where - >>::Mut: MappableMut, T>, -{ +impl>> CopyValue, S> { /// Deref the inner value mutably. - pub fn as_mut(&self) -> Option<, T>>::Mapped> { - S::Mut::map(self.try_write(), |v| v.as_mut()).ok() + pub fn as_mut( + &self, + ) -> Option<<>>::Mut as MappableMut>>::Mapped> { + S::Mut::try_map(self.write(), |v: &mut Option| v.as_mut()) } } @@ -291,20 +296,31 @@ impl> IntoIterator for Signal, S> { impl>>> Signal, S> where - S::Mut: MappableMut, T>, + <>>>::Mut as MappableMut< + SignalData>, + >>::Mapped>: MappableMut>, { /// Returns a reference to an element or `None` if out of bounds. pub fn get_mut( &self, index: usize, - ) -> Option, T>>::Mapped, S, Vec>> { - S::Mut::map(self.write(), |v| v.get_mut(index)) + ) -> Option< + Write< + T, + <<>>>::Mut as MappableMut>>>::Mapped< + Vec, + > as MappableMut>>::Mapped, + S, + Vec, + >, + > { + Write::filter_map(self.write(), |v| v.get_mut(index)) } } impl>>> Signal, S> { /// Returns a reference to an element or `None` if out of bounds. - pub fn as_mut(&self) -> Option>, S::Mut, S, Option>> { + pub fn as_mut(&self) -> Option>>>::Mut as MappableMut>>>::Mapped> as MappableMut>>::Mapped, S, Option>>{ Write::filter_map(self.write(), |v| v.as_mut()) } } diff --git a/packages/signals/src/rt.rs b/packages/signals/src/rt.rs index 3499de21a..7ae6365f7 100644 --- a/packages/signals/src/rt.rs +++ b/packages/signals/src/rt.rs @@ -11,32 +11,34 @@ use generational_box::{GenerationalBox, Owner}; use crate::Effect; -fn current_owner() -> Rc { - match Effect::current() { - // If we are inside of an effect, we should use the owner of the effect as the owner of the value. - Some(effect) => { - let scope_id = effect.source; - owner_in_scope(scope_id) - } - // Otherwise either get an owner from the current scope or create a new one. - None => match has_context() { - Some(rt) => rt, - None => { - let owner = Rc::new(current_store().owner()); - provide_context(owner).expect("in a virtual dom") - } - }, - } +fn current_owner, T>() -> Rc> { + todo!() + // match Effect::current() { + // // If we are inside of an effect, we should use the owner of the effect as the owner of the value. + // Some(effect) => { + // let scope_id = effect.source; + // owner_in_scope(scope_id) + // } + // // Otherwise either get an owner from the current scope or create a new one. + // None => match has_context() { + // Some(rt) => rt, + // None => { + // let owner = Rc::new(current_store().owner()); + // provide_context(owner).expect("in a virtual dom") + // } + // }, + // } } -fn owner_in_scope(scope: ScopeId) -> Rc { - match consume_context_from_scope(scope) { - Some(rt) => rt, - None => { - let owner = Rc::new(current_store().owner()); - provide_context_to_scope(scope, owner).expect("in a virtual dom") - } - } +fn owner_in_scope, T>(scope: ScopeId) -> Rc> { + todo!() + // match consume_context_from_scope(scope) { + // Some(rt) => rt, + // None => { + // let owner = Rc::new(current_store().owner()); + // provide_context_to_scope(scope, owner).expect("in a virtual dom") + // } + // } } #[derive(Debug)] @@ -48,13 +50,6 @@ pub struct CopyValue { origin_scope: ScopeId, } -impl Copy for CopyValue {} -impl Clone for CopyValue { - fn clone(&self) -> Self { - *self - } -} - #[cfg(feature = "serde")] impl serde::Serialize for CopyValue where diff --git a/packages/signals/src/selector.rs b/packages/signals/src/selector.rs index de3f206eb..28d8ca38e 100644 --- a/packages/signals/src/selector.rs +++ b/packages/signals/src/selector.rs @@ -75,7 +75,7 @@ where pub fn selector>>( mut f: impl FnMut() -> R + 'static, ) -> ReadOnlySignal { - let state = Signal:: { + let state = Signal:: { inner: CopyValue::invalid(), }; let effect = Effect { @@ -89,7 +89,6 @@ pub fn selector>>( } state.inner.value.set(SignalData { subscribers: Default::default(), - effect_subscribers: Default::default(), update_any: schedule_update_any().expect("in a virtual dom"), value: f(), effect_stack: get_effect_stack(), diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index a12b43648..501f736dd 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -1,5 +1,6 @@ use std::{ cell::RefCell, + marker::PhantomData, mem::MaybeUninit, ops::{Deref, DerefMut}, rc::Rc, @@ -10,8 +11,8 @@ use dioxus_core::{ prelude::{current_scope_id, has_context, provide_context, schedule_update_any}, ScopeId, ScopeState, }; -use generational_box::{AnyStorage, Mappable, MappableMut, Storage}; -use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard}; +use generational_box::{AnyStorage, Mappable, MappableMut, Storage, SyncStorage, UnsyncStorage}; +use parking_lot::RwLock; use crate::{get_effect_stack, CopyValue, Effect, EffectStack}; @@ -47,11 +48,51 @@ use crate::{get_effect_stack, CopyValue, Effect, EffectStack}; /// } /// ``` #[must_use] -pub fn use_signal>>( +pub fn use_signal(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal { + *cx.use_hook(|| Signal::new(f())) +} + +/// Creates a new `Send + Sync`` Signal. Signals are a Copy state management solution with automatic dependency tracking. +/// +/// ```rust +/// use dioxus::prelude::*; +/// use dioxus_signals::*; +/// +/// fn App(cx: Scope) -> Element { +/// let mut count = use_signal(cx, || 0); +/// +/// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated. +/// // The app component will never be rerendered in this example. +/// render! { Child { state: count } } +/// } +/// +/// #[component] +/// fn Child(cx: Scope, state: Signal) -> Element { +/// let state = *state; +/// +/// use_future!(cx, |()| async move { +/// // This signal is Send + Sync, so we can use it in an another thread +/// tokio::spawn(async move { +/// // Because the signal is a Copy type, we can use it in an async block without cloning it. +/// *state.write() += 1; +/// }).await; +/// }); +/// +/// render! { +/// button { +/// onclick: move |_| *state.write() += 1, +/// "{state}" +/// } +/// } +/// } +/// ``` +#[must_use] +pub fn use_signal_sync( cx: &ScopeState, f: impl FnOnce() -> T, -) -> Signal { - *cx.use_hook(|| Signal::new(f())) +) -> Signal { + // *cx.use_hook(|| Signal::new(f())) + todo!() } #[derive(Clone)] @@ -83,10 +124,15 @@ fn current_unsubscriber() -> Unsubscriber { } } +#[derive(Default)] +pub(crate) struct SignalSubscribers { + pub(crate) subscribers: Vec, + pub(crate) effect_subscribers: Vec, +} + pub(crate) struct SignalData { - pub(crate) subscribers: Rc>>, - pub(crate) effect_subscribers: Rc>>, - pub(crate) update_any: Arc, + pub(crate) subscribers: Arc>, + pub(crate) update_any: Arc, pub(crate) effect_stack: EffectStack, pub(crate) value: T, } @@ -123,7 +169,7 @@ pub(crate) struct SignalData { /// } /// } /// ``` -pub struct Signal { +pub struct Signal>> { pub(crate) inner: CopyValue, S>, } @@ -147,7 +193,6 @@ impl>> Signal { Self { inner: CopyValue::new(SignalData { subscribers: Default::default(), - effect_subscribers: Default::default(), update_any: schedule_update_any().expect("in a virtual dom"), value, effect_stack: get_effect_stack(), @@ -161,7 +206,6 @@ impl>> Signal { inner: CopyValue::new_in_scope( SignalData { subscribers: Default::default(), - effect_subscribers: Default::default(), update_any: schedule_update_any().expect("in a virtual dom"), value, effect_stack: get_effect_stack(), @@ -178,13 +222,13 @@ impl>> Signal { /// Get the current value of the signal. This will subscribe the current scope to the signal. /// If the signal has been dropped, this will panic. - pub fn read(&self) -> <>>::Ref as Mappable, T>>::Mapped - where - >>::Ref: Mappable, T>, - { + pub fn read( + &self, + ) -> <>>::Ref as Mappable>>::Mapped { let inner = self.inner.read(); if let Some(effect) = inner.effect_stack.current() { - let mut effect_subscribers = inner.effect_subscribers.borrow_mut(); + let mut subscribers = inner.subscribers.write(); + let mut effect_subscribers = &mut subscribers.effect_subscribers; if !effect_subscribers.contains(&effect) { effect_subscribers.push(effect); } @@ -196,12 +240,17 @@ impl>> Signal { self.inner.value, current_scope_id ); - let mut subscribers = inner.subscribers.borrow_mut(); + let mut subscribers = inner.subscribers.write(); + let subscribers = &mut subscribers.subscribers; if !subscribers.contains(¤t_scope_id) { subscribers.push(current_scope_id); drop(subscribers); let unsubscriber = current_unsubscriber(); - inner.subscribers.borrow_mut().push(unsubscriber.scope); + inner + .subscribers + .write() + .subscribers + .push(unsubscriber.scope); } } } @@ -212,22 +261,21 @@ impl>> Signal { /// If the signal has been dropped, this will panic. pub fn write( &self, - ) -> Write>>::Mut as MappableMut, T>>::Mapped, S> - where - >>::Mut: MappableMut, T>, + ) -> Write>>::Mut as MappableMut>>::Mapped, S> { let inner = self.inner.write(); let borrow = S::Mut::map(inner, |v| &mut v.value); Write { write: borrow, signal: SignalSubscriberDrop { signal: *self }, + phantom: std::marker::PhantomData, } } fn update_subscribers(&self) { { let inner = self.inner.read(); - for &scope_id in &*inner.subscribers.borrow() { + for &scope_id in &*inner.subscribers.read().subscribers { tracing::trace!( "Write on {:?} triggered update on {:?}", self.inner.value, @@ -239,7 +287,7 @@ impl>> Signal { let subscribers = { let self_read = self.inner.read(); - let mut effects = self_read.effect_subscribers.borrow_mut(); + let mut effects = &mut self_read.subscribers.write().effect_subscribers; std::mem::take(&mut *effects) }; for effect in subscribers { @@ -280,7 +328,7 @@ impl>> Signal { } } -impl> Signal { +impl>> Signal { /// Invert the boolean value of the signal. This will trigger an update on all subscribers. pub fn toggle(&self) { self.set(!self.value()); @@ -294,7 +342,8 @@ impl>> PartialEq for Signal { } impl>> Deref for Signal { - type Target = dyn Fn() -> S::Ref; + type Target = + dyn Fn() -> <>>::Ref as Mappable>>::Mapped; fn deref(&self) -> &Self::Target { // https://github.com/dtolnay/case-studies/tree/master/callable-types @@ -337,21 +386,25 @@ impl>> Drop for SignalSubscriberDrop } /// A mutable reference to a signal's value. -pub struct Write, S: Storage>, I: 'static = T> { +/// +/// T is the current type of the write +/// B is the dynamicly checked type of the write (RefMut) +/// S is the storage type of the signal +/// I is the type of the original signal +pub struct Write, S: Storage>, I: 'static = T> { write: B, signal: SignalSubscriberDrop, + phantom: std::marker::PhantomData, } -impl, S: Storage>, I: 'static> Write { +impl, S: Storage>, I: 'static> Write { /// Map the mutable reference to the signal's value to a new type. - pub fn map(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write - where - S: MappableMut, - { - let Self { write, signal } = myself; + pub fn map(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write, S, I> { + let Self { write, signal, .. } = myself; Write { - write: S::map(write, f), + write: B::map(write, f), signal, + phantom: std::marker::PhantomData, } } @@ -359,17 +412,18 @@ impl, S: Storage>, I: 'static> pub fn filter_map( myself: Self, f: impl FnOnce(&mut T) -> Option<&mut O>, - ) -> Option> - where - S: MappableMut, - { - let Self { write, signal } = myself; - let write = MappedRwLockWriteGuard::try_map(write, f).ok(); - write.map(|write| Write { write, signal }) + ) -> Option, S, I>> { + let Self { write, signal, .. } = myself; + let write = B::try_map(write, f); + write.map(|write| Write { + write, + signal, + phantom: PhantomData, + }) } } -impl, S: Storage>, I: 'static> Deref +impl, S: Storage>, I: 'static> Deref for Write { type Target = T; @@ -379,7 +433,7 @@ impl, S: Storage>, I: 'static> } } -impl, S: Storage>, I> DerefMut for Write { +impl, S: Storage>, I> DerefMut for Write { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.write } @@ -402,7 +456,9 @@ impl>> ReadOnlySignal { } /// Get the current value of the signal. This will subscribe the current scope to the signal. - pub fn read(&self) -> MappedRwLockReadGuard<'static, T> { + pub fn read( + &self, + ) -> <>>::Ref as Mappable>>::Mapped { self.inner.read() } @@ -426,7 +482,8 @@ impl>> PartialEq for ReadOnlySignal { } impl>> Deref for ReadOnlySignal { - type Target = dyn Fn() -> S::Ref; + type Target = + dyn Fn() -> <>>::Ref as Mappable>>::Mapped; fn deref(&self) -> &Self::Target { // https://github.com/dtolnay/case-studies/tree/master/callable-types