Skip to main content

smudge_core/
reactive.rs

1//! The reactive runtime: signals, memos, effects and owners driven by the frame.
2//!
3//! The core is a small signal engine written for Smudge. It is single-threaded
4//! and stores everything in one arena per thread. A signal write marks the
5//! effects it reaches and queues them; the effects run when the frame calls
6//! [`flush`], in the order they were woken, and writes made by an effect are
7//! picked up by the same flush. Nothing runs between flushes.
8//!
9//! Every thread owns its own runtime, so effects on two threads never share
10//! state. There is no executor to install and nothing to poll: call [`init`]
11//! if you want the runtime to exist before the first signal, but creating a
12//! signal does it too.
13//!
14//! A wake is reported to the callback set by [`set_wake_callback`], which is
15//! how the platform learns that the next frame has work to do. The callback
16//! belongs to the owner tree it was set under, so two apps on one thread each
17//! get their own redraw requests. It runs on the first wake of its tree after
18//! a flush and not again until the next flush ends. A write inside a flush
19//! that wakes a tree the flush already serves asks for nothing, and one that
20//! wakes another tree asks that tree for a redraw. While an app runs the
21//! part of its frame that flushes until no effect is left, its tree asks for
22//! nothing either, because the frame runs what the write woke. A wake is reported on the
23//! thread that writes the signal, so write signals only on the thread that
24//! runs their effects.
25//!
26//! ## Semantics
27//!
28//! - An effect runs once synchronously when it is created, and again from a
29//!   flush after a source it read changed.
30//! - An effect re-tracks its sources on every run, so conditional reads work.
31//! - A memo recomputes when read after a source changed, and stops
32//!   propagation when its new value compares equal. Memos are therefore
33//!   glitch-free: a reader never sees a memo that disagrees with its sources.
34//! - Effects are not glitch-free across effect-to-effect writes: an effect
35//!   that reads what another effect writes sees whichever value the wake
36//!   order gives it. Put a memo in between when that matters.
37//! - An effect that runs more than a fixed number of times in one flush is a
38//!   cycle. Debug builds panic; release builds stop running it for that
39//!   flush, so the frame finishes.
40//! - An effect whose body panics stays subscribed and runs again on the next
41//!   write to a source it reached.
42//! - Cleaning up an owner stops its effects and disposes its signals, children
43//!   first. Dropping the last handle to an owner cleans it up too, so mount
44//!   and unmount cycles return all of their memory.
45//!
46//! The reactive API is defined here, so a widget imports it from one place.
47//! Types are at the module root and the traits that give them their methods
48//! are in [`prelude`].
49//!
50//! ```
51//! use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
52//! use std::cell::Cell;
53//! use std::rc::Rc;
54//!
55//! reactive::init();
56//! let owner = Owner::new();
57//! owner.set();
58//!
59//! let (count, set_count) = reactive::signal_local(0u32);
60//! let seen = Rc::new(Cell::new(0u32));
61//! let recorder = Rc::clone(&seen);
62//! let _effect = RenderEffect::new(move || recorder.set(count.get()));
63//!
64//! set_count.set(1);
65//! assert_eq!(seen.get(), 0, "the write waits for the frame");
66//!
67//! reactive::flush();
68//! assert_eq!(seen.get(), 1);
69//! ```
70
71use std::any::TypeId;
72use std::cell::{Cell, RefCell};
73use std::rc::{Rc, Weak};
74
75pub(crate) mod runtime;
76
77use runtime::{CurrentOwnerGuard, EffectCell, MemoData, NodeId, OwnerData, OwnerState, SignalData};
78
79/// Installs the runtime on the calling thread.
80///
81/// Creating a signal, memo, effect or owner does this implicitly, so calling
82/// `init` is never required. It exists so a thread can state that it runs the
83/// reactive runtime, and so older call sites keep working. Calling it again
84/// does nothing.
85///
86/// # Examples
87///
88/// ```
89/// use smudge_core::reactive;
90///
91/// reactive::init();
92/// assert!(!reactive::flush(), "nothing was woken");
93/// ```
94pub fn init() {
95    runtime::with_runtime(|_| {});
96}
97
98/// Runs every effect woken since the last call, in the order they were woken,
99/// and returns whether any effect ran.
100///
101/// Call this once per frame, before reading the updates that effects
102/// produced. A write made while the flush runs has its effect run in the same
103/// call, so the return value covers everything that write set off.
104///
105/// Does nothing and returns `false` when called from inside a running flush,
106/// because that flush already drains the queue.
107///
108/// # Examples
109///
110/// ```
111/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
112///
113/// let owner = Owner::new();
114/// owner.set();
115/// let (count, set_count) = reactive::signal_local(0u32);
116/// let _effect = RenderEffect::new(move || count.get());
117///
118/// assert!(!reactive::flush(), "the creation run is not a flush");
119/// set_count.set(1);
120/// assert!(reactive::flush(), "the write woke the effect");
121/// assert!(!reactive::flush(), "nothing was woken since");
122/// ```
123pub fn flush() -> bool {
124    runtime::flush()
125}
126
127/// Sets the callback that a wake between flushes runs to request a redraw.
128///
129/// The callback is stored on the root scope of the current owner tree, which
130/// is the app whose owner is current. When no owner is current it is stored on
131/// the thread's default scope. Replaces any previous callback of that scope.
132///
133/// The callback runs on the first wake of its tree after a flush and not
134/// again until the next flush ends, so a frame that writes many signals
135/// requests one redraw. A wake that arrives during a flush asks for nothing
136/// when the tree already has an effect in that flush, because the flush
137/// applies the write itself.
138///
139/// A wake is reported on the thread that writes the signal, so write signals
140/// only on the thread that runs their effects.
141///
142/// # Examples
143///
144/// ```
145/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
146/// use std::cell::Cell;
147/// use std::rc::Rc;
148///
149/// let owner = Owner::new();
150/// owner.set();
151/// let redraws = Rc::new(Cell::new(0u32));
152/// let counter = Rc::clone(&redraws);
153/// reactive::set_wake_callback(move || counter.set(counter.get() + 1));
154///
155/// let (count, set_count) = reactive::signal_local(0u32);
156/// let _effect = RenderEffect::new(move || count.get());
157/// reactive::flush();
158///
159/// set_count.set(1);
160/// assert_eq!(redraws.get(), 1);
161/// ```
162pub fn set_wake_callback(callback: impl Fn() + 'static) {
163    // The previous callback drops after the runtime is released, so its drop
164    // may enter the runtime.
165    let scope = runtime::with_runtime(|runtime| runtime.current_scope());
166    scope.wake.replace(Some(Rc::new(callback)));
167}
168
169/// The traits and constructors that signals, memos and owners need.
170///
171/// Import this module with a glob to call `.get()`, `.set()` and `.update()`
172/// on reactive values, to read them with or without tracking, and to create
173/// signals and provide context.
174pub mod prelude {
175    pub use super::{Get, Read, Set, Update, With, provide_context, signal_local, use_context};
176}
177
178/// Applies a closure to a reactive value, tracking it as a source.
179pub trait With<T: ?Sized + 'static> {
180    /// Applies `fun` to the current value and returns its result.
181    ///
182    /// When an effect or a memo is running, the value becomes one of its
183    /// sources and a later change wakes it.
184    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U;
185}
186
187/// Applies a closure to a reactive value without tracking it.
188pub trait Read<T: ?Sized + 'static> {
189    /// Applies `fun` to the current value and returns its result.
190    ///
191    /// No source is recorded, so a later change wakes nothing through this
192    /// read.
193    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U;
194}
195
196/// Clones the value of a reactive value, tracking it as a source.
197pub trait Get<T: Clone + 'static>: With<T> {
198    /// Returns a clone of the current value.
199    fn get(&self) -> T {
200        self.with(T::clone)
201    }
202}
203
204impl<S, T> Get<T> for S
205where
206    S: With<T> + ?Sized,
207    T: Clone + 'static,
208{
209}
210
211/// Updates the value of a reactive value in place and notifies subscribers.
212pub trait Update<T: 'static> {
213    /// Applies `fun` to the value and notifies subscribers that it changed,
214    /// whether or not `fun` changed anything.
215    ///
216    /// # Panics
217    ///
218    /// Panics when the value is already mutably borrowed, which happens when
219    /// `fun` reads the same value.
220    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U;
221}
222
223/// Replaces the value of a reactive value and notifies subscribers.
224pub trait Set<T: 'static>: Update<T> {
225    /// Replaces the value and notifies subscribers, whether or not the new
226    /// value compares equal to the old one.
227    fn set(&self, value: T) {
228        self.update(|slot| *slot = value);
229    }
230}
231
232impl<S, T> Set<T> for S
233where
234    S: Update<T> + ?Sized,
235    T: 'static,
236{
237}
238
239/// A signal that can be read and written.
240///
241/// Created with [`RwSignal::new`], or split into a [`ReadSignal`] and a
242/// [`WriteSignal`] by [`signal_local`]. Cloning the handle is cheap, and
243/// every clone names the same signal.
244pub struct RwSignal<T> {
245    /// The value and the node that carries the subscribers.
246    data: Rc<SignalData<T>>,
247}
248
249impl<T: 'static> RwSignal<T> {
250    /// Creates a signal holding `value`, under the current owner.
251    ///
252    /// The signal is disposed when that owner is cleaned up. Handles that
253    /// outlive it keep the value readable but notify nothing. With no current
254    /// owner nothing disposes it, and its entry in the runtime stays until the
255    /// thread ends.
256    pub fn new(value: T) -> RwSignal<T> {
257        let node = runtime::with_runtime(runtime::Runtime::new_signal);
258        RwSignal {
259            data: Rc::new(SignalData {
260                value: RefCell::new(value),
261                node: Cell::new(node),
262            }),
263        }
264    }
265}
266
267impl<T: 'static> Clone for RwSignal<T> {
268    fn clone(&self) -> RwSignal<T> {
269        RwSignal {
270            data: Rc::clone(&self.data),
271        }
272    }
273}
274
275impl<T: 'static> Clone for ReadSignal<T> {
276    fn clone(&self) -> ReadSignal<T> {
277        ReadSignal {
278            data: Rc::clone(&self.data),
279        }
280    }
281}
282
283impl<T: 'static> Clone for WriteSignal<T> {
284    fn clone(&self) -> WriteSignal<T> {
285        WriteSignal {
286            data: Rc::clone(&self.data),
287        }
288    }
289}
290
291impl<T: 'static> Clone for Memo<T> {
292    fn clone(&self) -> Memo<T> {
293        Memo {
294            data: Rc::clone(&self.data),
295        }
296    }
297}
298
299impl<T: 'static> With<T> for RwSignal<T> {
300    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
301        runtime::track_read(self.data.node.get());
302        fun(&self.data.value.borrow())
303    }
304}
305
306impl<T: 'static> Read<T> for RwSignal<T> {
307    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
308        fun(&self.data.value.borrow())
309    }
310}
311
312impl<T: 'static> Update<T> for RwSignal<T> {
313    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U {
314        let result = fun(&mut self.data.value.borrow_mut());
315        let wake = runtime::with_runtime(|runtime| runtime.notify(self.data.node.get()));
316        runtime::fire_wakes(wake);
317        result
318    }
319}
320
321/// The read half of a signal. Cloning the handle is cheap, and every clone
322/// names the same value.
323pub struct ReadSignal<T> {
324    /// The value and the node that carries the subscribers.
325    data: Rc<SignalData<T>>,
326}
327
328impl<T: 'static> With<T> for ReadSignal<T> {
329    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
330        runtime::track_read(self.data.node.get());
331        fun(&self.data.value.borrow())
332    }
333}
334
335impl<T: 'static> Read<T> for ReadSignal<T> {
336    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
337        fun(&self.data.value.borrow())
338    }
339}
340
341/// The write half of a signal. Cloning the handle is cheap, and every clone
342/// writes the same value.
343pub struct WriteSignal<T> {
344    /// The value and the node that carries the subscribers.
345    data: Rc<SignalData<T>>,
346}
347
348impl<T: 'static> Update<T> for WriteSignal<T> {
349    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U {
350        let result = fun(&mut self.data.value.borrow_mut());
351        let wake = runtime::with_runtime(|runtime| runtime.notify(self.data.node.get()));
352        runtime::fire_wakes(wake);
353        result
354    }
355}
356
357/// Creates a signal and returns its read and write halves.
358///
359/// The signal is disposed when the current owner is cleaned up. Handles that
360/// outlive it keep the value readable but notify nothing. With no current
361/// owner nothing disposes it, and its entry in the runtime stays until the
362/// thread ends.
363///
364/// ```
365/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
366/// use std::cell::Cell;
367/// use std::rc::Rc;
368///
369/// let owner = Owner::new();
370/// owner.set();
371/// let (count, set_count) = signal_local(3u32);
372/// let seen = Rc::new(Cell::new(0u32));
373/// let recorder = Rc::clone(&seen);
374/// let _effect = RenderEffect::new(move || recorder.set(count.get()));
375/// reactive::flush();
376///
377/// set_count.update(|value| *value += 1);
378/// reactive::flush();
379/// assert_eq!(seen.get(), 4);
380/// ```
381pub fn signal_local<T: 'static>(value: T) -> (ReadSignal<T>, WriteSignal<T>) {
382    let node = runtime::with_runtime(runtime::Runtime::new_signal);
383    let data = Rc::new(SignalData {
384        value: RefCell::new(value),
385        node: Cell::new(node),
386    });
387    (
388        ReadSignal {
389            data: Rc::clone(&data),
390        },
391        WriteSignal { data },
392    )
393}
394
395/// A value computed from signals, recomputed when a read needs it.
396///
397/// A memo recomputes when it is read after one of its sources changed, and it
398/// stops propagation when the new value compares equal to the old one, so
399/// effects that read it do not rerun. Because a memo is always brought up to
400/// date on read, a reader never sees a memo that disagrees with its sources.
401///
402/// The memo is disposed when the current owner is cleaned up. Handles that
403/// outlive it keep the last value readable. With no current owner nothing
404/// disposes it, so its computation stays in the runtime until the thread
405/// ends. Cloning the handle is cheap, and every clone names the same memo.
406pub struct Memo<T> {
407    /// The value and the node that carries the subscribers.
408    data: Rc<MemoData<T>>,
409}
410
411impl<T: 'static> Memo<T> {
412    /// Creates a memo that computes its value with `compute`.
413    ///
414    /// The first computation runs at once, tracking the signals it reads into
415    /// the effect or memo that is running, if any.
416    ///
417    /// The value type needs [`PartialEq`] so the memo can recognize an
418    /// unchanged value and stop propagation.
419    pub fn new(compute: impl Fn() -> T + 'static) -> Memo<T>
420    where
421        T: PartialEq,
422    {
423        let data = Rc::new(MemoData {
424            value: RefCell::new(None),
425            node: Cell::new(NodeId::default()),
426        });
427        let stored = Rc::clone(&data);
428        let run: Rc<dyn Fn()> = Rc::new(move || {
429            let value = compute();
430            let changed = stored
431                .value
432                .borrow()
433                .as_ref()
434                .is_none_or(|old| *old != value);
435            if changed {
436                *stored.value.borrow_mut() = Some(value);
437                let wake = runtime::with_runtime(|runtime| runtime.notify(stored.node.get()));
438                runtime::fire_wakes(wake);
439            }
440        });
441        let node = runtime::with_runtime(|runtime| runtime.new_memo(run));
442        data.node.set(node);
443        runtime::compute_new_memo(node);
444        Memo { data }
445    }
446}
447
448impl<T: 'static> With<T> for Memo<T> {
449    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
450        runtime::update_memo(self.data.node.get());
451        runtime::track_read(self.data.node.get());
452        let value = self.data.value.borrow();
453        fun(value.as_ref().expect(
454            "a memo holds a value once its first computation finished, so a \
455             read sees one unless the memo reads itself",
456        ))
457    }
458}
459
460impl<T: 'static> Read<T> for Memo<T> {
461    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
462        runtime::update_memo(self.data.node.get());
463        let value = self.data.value.borrow();
464        fun(value.as_ref().expect(
465            "a memo holds a value once its first computation finished, so a \
466             read sees one unless the memo reads itself",
467        ))
468    }
469}
470
471/// A function that reruns when a signal or memo it read changes.
472///
473/// The first run happens when the effect is created, with tracking, so the
474/// sources it reaches are the ones that wake it later. Every run re-tracks
475/// from scratch, which makes conditional reads work.
476///
477/// The effect is owned by the current owner: cleaning that owner up, or
478/// dropping its last handle, stops the effect and frees its closure. Created
479/// with no current owner, the effect lives until the returned handle drops.
480/// Dropping the handle of an owned effect does nothing.
481///
482/// A write inside an effect body queues the effect again, and a body that
483/// keeps waking itself is stopped at a fixed number of runs per flush:
484/// debug builds panic, release builds skip the effect for the rest of that
485/// flush.
486pub struct RenderEffect {
487    /// The node that carries the sources, the queue state and the body.
488    node: NodeId,
489    /// Whether an owner took responsibility for disposing the node.
490    owned: bool,
491}
492
493impl RenderEffect {
494    /// Creates an effect and runs its body once, with tracking.
495    ///
496    /// The effect is owned by the current owner, when there is one. See the
497    /// type's documentation for the lifetime rules. The body's return value
498    /// is ignored.
499    pub fn new<T>(mut run: impl FnMut() -> T + 'static) -> RenderEffect {
500        let owned = runtime::with_runtime(|runtime| runtime.current_owner().is_some());
501        let scope = runtime::with_runtime(|runtime| runtime.current_scope());
502        let cell = Rc::new(EffectCell {
503            run: RefCell::new(Some(Box::new(move || {
504                run();
505            }))),
506        });
507        let node = runtime::with_runtime(|runtime| runtime.new_effect(Rc::clone(&cell), scope));
508        let mut guard = runtime::DisposeOnUnwind {
509            node,
510            armed: !owned,
511        };
512        runtime::run_body(&cell, node);
513        guard.armed = false;
514        RenderEffect { node, owned }
515    }
516}
517
518impl Drop for RenderEffect {
519    fn drop(&mut self) {
520        if !self.owned {
521            runtime::dispose(self.node);
522        }
523    }
524}
525
526/// The owner of the reactive values and effects created while it is current.
527///
528/// Owners form a tree. [`Owner::new`] attaches to the current owner when there
529/// is one, [`Owner::child`] attaches to an owner directly, and [`Owner::set`]
530/// and [`Owner::with`] make one current, which is where new values and effects
531/// are registered. [`Owner::cleanup`] stops the owner's effects and disposes
532/// its values, children first; dropping the last handle to an owner does the
533/// same, so nothing has to be cleaned up by hand.
534///
535/// Context values are provided on an owner with [`provide_context`] and read
536/// by the owner and its descendants with [`use_context`].
537#[derive(Clone)]
538pub struct Owner {
539    /// The parent, scope and contents of the owner.
540    inner: Rc<OwnerData>,
541}
542
543impl Default for Owner {
544    fn default() -> Owner {
545        Owner::new()
546    }
547}
548
549impl Owner {
550    /// Creates an owner under the current owner, when there is one.
551    ///
552    /// With no current owner the new owner starts a new root scope, which
553    /// carries its own wake callback.
554    pub fn new() -> Owner {
555        let parent = runtime::with_runtime(|runtime| runtime.current_owner());
556        let scope = runtime::with_runtime(|runtime| runtime.owner_scope(parent.as_deref()));
557        let inner = Rc::new(OwnerData {
558            parent: parent.as_ref().map(Rc::downgrade),
559            scope,
560            cleaned: Cell::new(false),
561            state: RefCell::new(OwnerState::default()),
562            timer_book: RefCell::new(None),
563            clipboard: RefCell::new(None),
564            channel_book: RefCell::new(None),
565            window_book: RefCell::new(None),
566        });
567        if let Some(parent) = parent {
568            parent.adopt(&inner);
569        }
570        Owner { inner }
571    }
572
573    /// Creates an owner under this one.
574    ///
575    /// The child inherits this owner's root scope, so its effects wake the
576    /// same redraw requests.
577    pub fn child(&self) -> Owner {
578        self.inner.child()
579    }
580
581    /// Makes this owner current until another one is set or a `with` block
582    /// restores the previous one.
583    pub fn set(&self) {
584        runtime::with_runtime(|runtime| runtime.set_current(&self.inner));
585    }
586
587    /// Runs `fun` with this owner current, restoring the previous one after.
588    pub fn with<T>(&self, fun: impl FnOnce() -> T) -> T {
589        let _guard = CurrentOwnerGuard::enter(&self.inner);
590        fun()
591    }
592
593    /// Stops the owner's effects and disposes the values created under it,
594    /// children first, then runs the cleanup functions that
595    /// [`Owner::on_cleanup`] registered.
596    ///
597    /// Running it twice does nothing. Dropping the last handle to the owner
598    /// runs it too.
599    pub fn cleanup(&self) {
600        self.inner.cleanup();
601    }
602
603    /// Sets the callback that a wake in this owner's tree runs to request a
604    /// redraw.
605    ///
606    /// Every effect created under this owner reports its wake here, so two
607    /// owners on one thread each get their own redraw requests. See
608    /// [`set_wake_callback`] for when the callback runs.
609    pub fn set_wake_callback(&self, callback: impl Fn() + 'static) {
610        self.inner.scope.wake.replace(Some(Rc::new(callback)));
611    }
612
613    /// Registers `fun` to run when the current owner is cleaned up.
614    ///
615    /// With no current owner, `fun` is dropped.
616    pub fn on_cleanup(fun: impl FnOnce() + 'static) {
617        let Some(owner) = Owner::current() else {
618            return;
619        };
620        owner.state.borrow_mut().cleanups.push(Box::new(fun));
621    }
622
623    /// Returns the current owner, when one is set and still alive.
624    fn current() -> Option<Rc<OwnerData>> {
625        runtime::with_runtime(|runtime| runtime.current_owner())
626    }
627
628    /// Runs the wake callback of this owner's tree, when one is set.
629    ///
630    /// The callback runs outside the runtime, so it may write signals.
631    pub(crate) fn wake(&self) {
632        let callback = self.inner.scope.wake.borrow().clone();
633        if let Some(callback) = callback {
634            callback();
635        }
636    }
637
638    /// Returns the owner's data, for the crate's own wiring such as the
639    /// timer book an app installs on its root owner.
640    pub(crate) fn data(&self) -> &Rc<OwnerData> {
641        &self.inner
642    }
643}
644
645impl Drop for Owner {
646    fn drop(&mut self) {
647        if Rc::strong_count(&self.inner) == 1 {
648            self.inner.cleanup();
649        }
650    }
651}
652
653/// Stores `value` on the current owner for [`use_context`] to read.
654///
655/// The value is visible to the owner it was provided on and to everything
656/// created under it, and invisible to its siblings and ancestors. A second
657/// value of the same type replaces the first.
658///
659/// With no current owner, `value` is dropped.
660pub fn provide_context<T: 'static>(value: T) {
661    let Some(owner) = Owner::current() else {
662        return;
663    };
664    let key = TypeId::of::<T>();
665    let value: Rc<dyn std::any::Any> = Rc::new(value);
666    let mut state = owner.state.borrow_mut();
667    match state
668        .contexts
669        .iter_mut()
670        .find(|(existing, _)| *existing == key)
671    {
672        Some((_, slot)) => *slot = value,
673        None => state.contexts.push((key, value)),
674    }
675}
676
677/// Returns a clone of the context value of type `T`, provided on the current
678/// owner or the closest ancestor that provided one.
679///
680/// Returns `None` when neither has one.
681pub fn use_context<T: Clone + 'static>() -> Option<T> {
682    let key = TypeId::of::<T>();
683    let mut current = Owner::current();
684    while let Some(owner) = current {
685        let found = owner
686            .state
687            .borrow()
688            .contexts
689            .iter()
690            .find(|(existing, _)| *existing == key)
691            .map(|(_, value)| Rc::clone(value));
692        if let Some(value) = found
693            && let Ok(value) = value.downcast::<T>()
694        {
695            return Some(T::clone(&value));
696        }
697        current = owner.parent.as_ref().and_then(Weak::upgrade);
698    }
699    None
700}