Browse Source

fix: use typeid of atoms for their unique ID (#558)

Jon Kelley 2 years ago
parent
commit
bf9901a6cd

+ 6 - 3
packages/fermi/src/atoms/atom.rs

@@ -3,7 +3,7 @@ use crate::{AtomId, AtomRoot, Readable, Writable};
 pub type Atom<T> = fn(AtomBuilder) -> T;
 pub struct AtomBuilder;
 
-impl<V> Readable<V> for Atom<V> {
+impl<V: 'static> Readable<V> for Atom<V> {
     fn read(&self, _root: AtomRoot) -> Option<V> {
         todo!()
     }
@@ -11,11 +11,14 @@ impl<V> Readable<V> for Atom<V> {
         (*self)(AtomBuilder)
     }
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        AtomId {
+            ptr: *self as *const (),
+            type_id: std::any::TypeId::of::<V>(),
+        }
     }
 }
 
-impl<V> Writable<V> for Atom<V> {
+impl<V: 'static> Writable<V> for Atom<V> {
     fn write(&self, _root: AtomRoot, _value: V) {
         todo!()
     }

+ 6 - 3
packages/fermi/src/atoms/atomfamily.rs

@@ -4,7 +4,7 @@ use im_rc::HashMap as ImMap;
 pub struct AtomFamilyBuilder;
 pub type AtomFamily<K, V> = fn(AtomFamilyBuilder) -> ImMap<K, V>;
 
-impl<K, V> Readable<ImMap<K, V>> for AtomFamily<K, V> {
+impl<K, V: 'static> Readable<ImMap<K, V>> for AtomFamily<K, V> {
     fn read(&self, _root: AtomRoot) -> Option<ImMap<K, V>> {
         todo!()
     }
@@ -14,11 +14,14 @@ impl<K, V> Readable<ImMap<K, V>> for AtomFamily<K, V> {
     }
 
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        AtomId {
+            ptr: *self as *const (),
+            type_id: std::any::TypeId::of::<V>(),
+        }
     }
 }
 
-impl<K, V> Writable<ImMap<K, V>> for AtomFamily<K, V> {
+impl<K, V: 'static> Writable<ImMap<K, V>> for AtomFamily<K, V> {
     fn write(&self, _root: AtomRoot, _value: ImMap<K, V>) {
         todo!()
     }

+ 5 - 2
packages/fermi/src/atoms/atomref.rs

@@ -4,7 +4,7 @@ use std::cell::RefCell;
 pub struct AtomRefBuilder;
 pub type AtomRef<T> = fn(AtomRefBuilder) -> T;
 
-impl<V> Readable<RefCell<V>> for AtomRef<V> {
+impl<V: 'static> Readable<RefCell<V>> for AtomRef<V> {
     fn read(&self, _root: AtomRoot) -> Option<RefCell<V>> {
         todo!()
     }
@@ -14,7 +14,10 @@ impl<V> Readable<RefCell<V>> for AtomRef<V> {
     }
 
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        AtomId {
+            ptr: *self as *const (),
+            type_id: std::any::TypeId::of::<V>(),
+        }
     }
 }
 

+ 21 - 3
packages/fermi/src/root.rs

@@ -1,11 +1,21 @@
-use std::{any::Any, cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
+use std::{
+    any::{Any, TypeId},
+    cell::RefCell,
+    collections::HashMap,
+    rc::Rc,
+    sync::Arc,
+};
 
 use dioxus_core::ScopeId;
 use im_rc::HashSet;
 
 use crate::Readable;
 
-pub type AtomId = *const ();
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct AtomId {
+    pub(crate) ptr: *const (),
+    pub(crate) type_id: TypeId,
+}
 
 pub struct AtomRoot {
     pub atoms: RefCell<HashMap<AtomId, Slot>>,
@@ -44,7 +54,15 @@ impl AtomRoot {
         // initialize the value if it's not already initialized
         if let Some(slot) = atoms.get_mut(&f.unique_id()) {
             slot.subscribers.insert(scope);
-            slot.value.clone().downcast().unwrap()
+            match slot.value.clone().downcast() {
+                Ok(res) => res,
+                Err(e) => panic!(
+                    "Downcasting atom failed: {:?}. Has typeid of {:?} but needs typeid of {:?}",
+                    f.unique_id(),
+                    e.type_id(),
+                    TypeId::of::<V>()
+                ),
+            }
         } else {
             let value = Rc::new(f.init());
             let mut subscribers = HashSet::new();