Pārlūkot izejas kodu

Fix the issue of duplicate unique ID for atoms using `newtype`.

The MergeFunctionsPass in LLVM merges identical functions (https://rust.godbolt.org/z/3nnr9nMne), resulting in the same function addresses.
DianQK 2 gadi atpakaļ
vecāks
revīzija
535435a4cf

+ 3 - 1
.github/workflows/macos.yml

@@ -33,4 +33,6 @@ jobs:
       - uses: dtolnay/rust-toolchain@stable
       - uses: dtolnay/rust-toolchain@stable
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
       - uses: actions/checkout@v3
       - uses: actions/checkout@v3
-      - run: cargo test --all --tests
+      - run: |
+          cargo test --all --tests
+          cargo test --package fermi --release

+ 1 - 0
.github/workflows/windows.yml

@@ -85,4 +85,5 @@ jobs:
           set RUST_BACKTRACE=1
           set RUST_BACKTRACE=1
           cargo build --all --tests --examples
           cargo build --all --tests --examples
           cargo test --all --tests
           cargo test --all --tests
+          cargo test --package fermi --release
         shell: cmd
         shell: cmd

+ 2 - 2
docs/guide/src/en/__unused/advanced-guides/12-signals.md

@@ -95,7 +95,7 @@ Calling `deref` or `deref_mut` is actually more complex than it seems. When a va
 Sometimes you want a signal to propagate across your app, either through far-away siblings or through deeply-nested components. In these cases, we use Dirac: Dioxus's first-class state management toolkit. Dirac atoms automatically implement the Signal API. This component will bind the input element to the `TITLE` atom.
 Sometimes you want a signal to propagate across your app, either through far-away siblings or through deeply-nested components. In these cases, we use Dirac: Dioxus's first-class state management toolkit. Dirac atoms automatically implement the Signal API. This component will bind the input element to the `TITLE` atom.
 
 
 ```rust
 ```rust
-const TITLE: Atom<String> = || "".to_string();
+const TITLE: Atom<String> = Atom(|| "".to_string());
 const Provider: Component = |cx|{
 const Provider: Component = |cx|{
     let title = use_signal(cx, &TITLE);
     let title = use_signal(cx, &TITLE);
     render!(input { value: title })
     render!(input { value: title })
@@ -131,7 +131,7 @@ By default, Dioxus is limited when you use iter/map. With the `For` component, y
 Dioxus automatically understands how to use your signals when mixed with iterators through `Deref`/`DerefMut`. This lets you efficiently map collections while avoiding the re-rendering of lists. In essence, signals act as a hint to Dioxus on how to avoid un-necessary checks and renders, making your app faster.
 Dioxus automatically understands how to use your signals when mixed with iterators through `Deref`/`DerefMut`. This lets you efficiently map collections while avoiding the re-rendering of lists. In essence, signals act as a hint to Dioxus on how to avoid un-necessary checks and renders, making your app faster.
 
 
 ```rust
 ```rust
-const DICT: AtomFamily<String, String> = |_| {};
+const DICT: AtomFamily<String, String> = AtomFamily(|_| {});
 const List: Component = |cx|{
 const List: Component = |cx|{
     let dict = use_signal(cx, &DICT);
     let dict = use_signal(cx, &DICT);
     cx.render(rsx!(
     cx.render(rsx!(

+ 4 - 4
docs/guide/src/en/async/use_coroutine.md

@@ -146,7 +146,7 @@ async fn editor_service(rx: UnboundedReceiver<EditorCommand>) {
 We can combine coroutines with [Fermi](https://docs.rs/fermi/latest/fermi/index.html) to emulate Redux Toolkit's Thunk system with much less headache. This lets us store all of our app's state *within* a task and then simply update the "view" values stored in Atoms. It cannot be understated how powerful this technique is: we get all the perks of native Rust tasks with the optimizations and ergonomics of global state. This means your *actual* state does not need to be tied up in a system like Fermi or Redux – the only Atoms that need to exist are those that are used to drive the display/UI.
 We can combine coroutines with [Fermi](https://docs.rs/fermi/latest/fermi/index.html) to emulate Redux Toolkit's Thunk system with much less headache. This lets us store all of our app's state *within* a task and then simply update the "view" values stored in Atoms. It cannot be understated how powerful this technique is: we get all the perks of native Rust tasks with the optimizations and ergonomics of global state. This means your *actual* state does not need to be tied up in a system like Fermi or Redux – the only Atoms that need to exist are those that are used to drive the display/UI.
 
 
 ```rust
 ```rust
-static USERNAME: Atom<String> = |_| "default".to_string();
+static USERNAME: Atom<String> = Atom(|_| "default".to_string());
 
 
 fn app(cx: Scope) -> Element {
 fn app(cx: Scope) -> Element {
     let atoms = use_atom_root(cx);
     let atoms = use_atom_root(cx);
@@ -159,7 +159,7 @@ fn app(cx: Scope) -> Element {
 }
 }
 
 
 fn Banner(cx: Scope) -> Element {
 fn Banner(cx: Scope) -> Element {
-    let username = use_read(cx, USERNAME);
+    let username = use_read(cx, &USERNAME);
 
 
     cx.render(rsx!{
     cx.render(rsx!{
         h1 { "Welcome back, {username}" }
         h1 { "Welcome back, {username}" }
@@ -177,8 +177,8 @@ enum SyncAction {
 }
 }
 
 
 async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
 async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
-    let username = atoms.write(USERNAME);
-    let errors = atoms.write(ERRORS);
+    let username = atoms.write(&USERNAME);
+    let errors = atoms.write(&ERRORS);
 
 
     while let Ok(msg) = rx.next().await {
     while let Ok(msg) = rx.next().await {
         match msg {
         match msg {

+ 3 - 3
docs/guide/src/en/best_practices/error_handling.md

@@ -118,14 +118,14 @@ enum InputError {
     TooShort,
     TooShort,
 }
 }
 
 
-static INPUT_ERROR: Atom<InputError> = |_| InputError::None;
+static INPUT_ERROR: Atom<InputError> = Atom(|_| InputError::None);
 ```
 ```
 
 
 Then, in our top level component, we want to explicitly handle the possible error state for this part of the tree.
 Then, in our top level component, we want to explicitly handle the possible error state for this part of the tree.
 
 
 ```rust
 ```rust
 fn TopLevel(cx: Scope) -> Element {
 fn TopLevel(cx: Scope) -> Element {
-    let error = use_read(cx, INPUT_ERROR);
+    let error = use_read(cx, &INPUT_ERROR);
 
 
     match error {
     match error {
         TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
         TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
@@ -139,7 +139,7 @@ Now, whenever a downstream component has an error in its actions, it can simply
 
 
 ```rust
 ```rust
 fn Commandline(cx: Scope) -> Element {
 fn Commandline(cx: Scope) -> Element {
-    let set_error = use_set(cx, INPUT_ERROR);
+    let set_error = use_set(cx, &INPUT_ERROR);
 
 
     cx.render(rsx!{
     cx.render(rsx!{
         input {
         input {

+ 4 - 4
docs/guide/src/pt-br/async/use_coroutine.md

@@ -105,7 +105,7 @@ async fn editor_service(rx: UnboundedReceiver<EditorCommand>) {
 Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux Toolkit** com muito menos dor de cabeça. Isso nos permite armazenar todo o estado do nosso aplicativo _dentro_ de uma tarefa e, em seguida, simplesmente atualizar os valores de "visualização" armazenados em `Atoms`. Não pode ser subestimado o quão poderosa é essa técnica: temos todas as vantagens das tarefas nativas do Rust com as otimizações e ergonomia do estado global. Isso significa que seu estado _real_ não precisa estar vinculado a um sistema como `Fermi` ou `Redux` – os únicos `Atoms` que precisam existir são aqueles que são usados para controlar a interface.
 Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux Toolkit** com muito menos dor de cabeça. Isso nos permite armazenar todo o estado do nosso aplicativo _dentro_ de uma tarefa e, em seguida, simplesmente atualizar os valores de "visualização" armazenados em `Atoms`. Não pode ser subestimado o quão poderosa é essa técnica: temos todas as vantagens das tarefas nativas do Rust com as otimizações e ergonomia do estado global. Isso significa que seu estado _real_ não precisa estar vinculado a um sistema como `Fermi` ou `Redux` – os únicos `Atoms` que precisam existir são aqueles que são usados para controlar a interface.
 
 
 ```rust
 ```rust
-static USERNAME: Atom<String> = |_| "default".to_string();
+static USERNAME: Atom<String> = Atom(|_| "default".to_string());
 
 
 fn app(cx: Scope) -> Element {
 fn app(cx: Scope) -> Element {
     let atoms = use_atom_root(cx);
     let atoms = use_atom_root(cx);
@@ -118,7 +118,7 @@ fn app(cx: Scope) -> Element {
 }
 }
 
 
 fn Banner(cx: Scope) -> Element {
 fn Banner(cx: Scope) -> Element {
-    let username = use_read(cx, USERNAME);
+    let username = use_read(cx, &USERNAME);
 
 
     cx.render(rsx!{
     cx.render(rsx!{
         h1 { "Welcome back, {username}" }
         h1 { "Welcome back, {username}" }
@@ -134,8 +134,8 @@ enum SyncAction {
 }
 }
 
 
 async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
 async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
-    let username = atoms.write(USERNAME);
-    let errors = atoms.write(ERRORS);
+    let username = atoms.write(&USERNAME);
+    let errors = atoms.write(&ERRORS);
 
 
     while let Ok(msg) = rx.next().await {
     while let Ok(msg) = rx.next().await {
         match msg {
         match msg {

+ 3 - 3
docs/guide/src/pt-br/best_practices/error_handling.md

@@ -113,14 +113,14 @@ enum InputError {
     TooShort,
     TooShort,
 }
 }
 
 
-static INPUT_ERROR: Atom<InputError> = |_| InputError::None;
+static INPUT_ERROR: Atom<InputError> = Atom(|_| InputError::None);
 ```
 ```
 
 
 Então, em nosso componente de nível superior, queremos tratar explicitamente o possível estado de erro para esta parte da árvore.
 Então, em nosso componente de nível superior, queremos tratar explicitamente o possível estado de erro para esta parte da árvore.
 
 
 ```rust
 ```rust
 fn TopLevel(cx: Scope) -> Element {
 fn TopLevel(cx: Scope) -> Element {
-    let error = use_read(cx, INPUT_ERROR);
+    let error = use_read(cx, &INPUT_ERROR);
 
 
     match error {
     match error {
         TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
         TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
@@ -134,7 +134,7 @@ Agora, sempre que um componente _downstream_ tiver um erro em suas ações, ele
 
 
 ```rust
 ```rust
 fn Commandline(cx: Scope) -> Element {
 fn Commandline(cx: Scope) -> Element {
-    let set_error = use_set(cx, INPUT_ERROR);
+    let set_error = use_set(cx, &INPUT_ERROR);
 
 
     cx.render(rsx!{
     cx.render(rsx!{
         input {
         input {

+ 5 - 5
examples/fermi.rs

@@ -7,11 +7,11 @@ fn main() {
     dioxus_desktop::launch(app)
     dioxus_desktop::launch(app)
 }
 }
 
 
-static NAME: Atom<String> = |_| "world".to_string();
+static NAME: Atom<String> = Atom(|_| "world".to_string());
 
 
 fn app(cx: Scope) -> Element {
 fn app(cx: Scope) -> Element {
     use_init_atom_root(cx);
     use_init_atom_root(cx);
-    let name = use_read(cx, NAME);
+    let name = use_read(cx, &NAME);
 
 
     cx.render(rsx! {
     cx.render(rsx! {
         div { "hello {name}!" }
         div { "hello {name}!" }
@@ -21,7 +21,7 @@ fn app(cx: Scope) -> Element {
 }
 }
 
 
 fn Child(cx: Scope) -> Element {
 fn Child(cx: Scope) -> Element {
-    let set_name = use_set(cx, NAME);
+    let set_name = use_set(cx, &NAME);
 
 
     cx.render(rsx! {
     cx.render(rsx! {
         button {
         button {
@@ -31,10 +31,10 @@ fn Child(cx: Scope) -> Element {
     })
     })
 }
 }
 
 
-static NAMES: AtomRef<Vec<String>> = |_| vec!["world".to_string()];
+static NAMES: AtomRef<Vec<String>> = AtomRef(|_| vec!["world".to_string()]);
 
 
 fn ChildWithRef(cx: Scope) -> Element {
 fn ChildWithRef(cx: Scope) -> Element {
-    let names = use_atom_ref(cx, NAMES);
+    let names = use_atom_ref(cx, &NAMES);
 
 
     cx.render(rsx! {
     cx.render(rsx! {
         div {
         div {

+ 10 - 10
packages/fermi/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <div align="center">
   <h1>Fermi ⚛</h1>
   <h1>Fermi ⚛</h1>
   <p>
   <p>
@@ -6,7 +5,6 @@
   </p>
   </p>
 </div>
 </div>
 
 
-
 <div align="center">
 <div align="center">
   <!-- Crates version -->
   <!-- Crates version -->
   <a href="https://crates.io/crates/dioxus">
   <a href="https://crates.io/crates/dioxus">
@@ -30,21 +28,21 @@
   </a>
   </a>
 </div>
 </div>
 
 
------
+---
 
 
 Fermi is a global state management solution for Dioxus that's as easy as `use_state`.
 Fermi is a global state management solution for Dioxus that's as easy as `use_state`.
 
 
 Inspired by atom-based state management solutions, all state in Fermi starts as an `atom`:
 Inspired by atom-based state management solutions, all state in Fermi starts as an `atom`:
 
 
 ```rust, ignore
 ```rust, ignore
-static NAME: Atom<&str> = |_| "Dioxus";
+static NAME: Atom<&str> = Atom(|_| "Dioxus");
 ```
 ```
 
 
 From anywhere in our app, we can read the value of our atom:
 From anywhere in our app, we can read the value of our atom:
 
 
-```rust, ignores
+```rust, ignore
 fn NameCard(cx: Scope) -> Element {
 fn NameCard(cx: Scope) -> Element {
-    let name = use_read(cx, NAME);
+    let name = use_read(cx, &NAME);
     cx.render(rsx!{ h1 { "Hello, {name}"} })
     cx.render(rsx!{ h1 { "Hello, {name}"} })
 }
 }
 ```
 ```
@@ -53,7 +51,7 @@ We can also set the value of our atom, also from anywhere in our app:
 
 
 ```rust, ignore
 ```rust, ignore
 fn NameCard(cx: Scope) -> Element {
 fn NameCard(cx: Scope) -> Element {
-    let set_name = use_set(cx, NAME);
+    let set_name = use_set(cx, &NAME);
     cx.render(rsx!{
     cx.render(rsx!{
         button {
         button {
             onclick: move |_| set_name("Fermi"),
             onclick: move |_| set_name("Fermi"),
@@ -66,10 +64,10 @@ fn NameCard(cx: Scope) -> Element {
 If needed, we can update the atom's value, based on itself:
 If needed, we can update the atom's value, based on itself:
 
 
 ```rust, ignore
 ```rust, ignore
-static COUNT: Atom<i32> = |_| 0;
+static COUNT: Atom<i32> = Atom(|_| 0);
 
 
 fn Counter(cx: Scope) -> Element {
 fn Counter(cx: Scope) -> Element {
-    let mut count = use_atom_state(cx, COUNT);
+    let mut count = use_atom_state(cx, &COUNT);
 
 
     cx.render(rsx!{
     cx.render(rsx!{
         p {
         p {
@@ -86,6 +84,7 @@ fn Counter(cx: Scope) -> Element {
 It's that simple!
 It's that simple!
 
 
 ## Installation
 ## Installation
+
 Fermi is currently under construction, so you have to use the `master` branch to get started.
 Fermi is currently under construction, so you have to use the `master` branch to get started.
 
 
 ```toml
 ```toml
@@ -93,10 +92,10 @@ Fermi is currently under construction, so you have to use the `master` branch to
 fermi = { git = "https://github.com/dioxuslabs/dioxus" }
 fermi = { git = "https://github.com/dioxuslabs/dioxus" }
 ```
 ```
 
 
-
 ## Running examples
 ## Running examples
 
 
 The examples here use Dioxus Desktop to showcase their functionality. To run an example, use
 The examples here use Dioxus Desktop to showcase their functionality. To run an example, use
+
 ```sh
 ```sh
 $ cargo run --example fermi
 $ cargo run --example fermi
 ```
 ```
@@ -104,6 +103,7 @@ $ cargo run --example fermi
 ## Features
 ## Features
 
 
 Broadly our feature set required to be released includes:
 Broadly our feature set required to be released includes:
+
 - [x] Support for Atoms
 - [x] Support for Atoms
 - [x] Support for AtomRef (for values that aren't `Clone`)
 - [x] Support for AtomRef (for values that aren't `Clone`)
 - [ ] Support for Atom Families
 - [ ] Support for Atom Families

+ 23 - 7
packages/fermi/src/atoms/atom.rs

@@ -1,21 +1,21 @@
 use crate::{AtomId, AtomRoot, Readable, Writable};
 use crate::{AtomId, AtomRoot, Readable, Writable};
 
 
-pub type Atom<T> = fn(AtomBuilder) -> T;
+pub struct Atom<T>(pub fn(AtomBuilder) -> T);
 pub struct AtomBuilder;
 pub struct AtomBuilder;
 
 
-impl<V> Readable<V> for Atom<V> {
+impl<V> Readable<V> for &'static Atom<V> {
     fn read(&self, _root: AtomRoot) -> Option<V> {
     fn read(&self, _root: AtomRoot) -> Option<V> {
         todo!()
         todo!()
     }
     }
     fn init(&self) -> V {
     fn init(&self) -> V {
-        (*self)(AtomBuilder)
+        self.0(AtomBuilder)
     }
     }
     fn unique_id(&self) -> AtomId {
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        *self as *const Atom<V> as *const ()
     }
     }
 }
 }
 
 
-impl<V> Writable<V> for Atom<V> {
+impl<V> Writable<V> for &'static Atom<V> {
     fn write(&self, _root: AtomRoot, _value: V) {
     fn write(&self, _root: AtomRoot, _value: V) {
         todo!()
         todo!()
     }
     }
@@ -23,6 +23,22 @@ impl<V> Writable<V> for Atom<V> {
 
 
 #[test]
 #[test]
 fn atom_compiles() {
 fn atom_compiles() {
-    static TEST_ATOM: Atom<&str> = |_| "hello";
-    dbg!(TEST_ATOM.init());
+    static TEST_ATOM: Atom<&str> = Atom(|_| "hello");
+    dbg!((&TEST_ATOM).init());
+}
+
+#[test]
+fn atom_is_unique() {
+    static TEST_ATOM_1: Atom<&str> = Atom(|_| "hello");
+    static TEST_ATOM_2: Atom<&str> = Atom(|_| "hello");
+    assert_eq!((&TEST_ATOM_1).unique_id(), (&TEST_ATOM_1).unique_id());
+    assert_ne!((&TEST_ATOM_1).unique_id(), (&TEST_ATOM_2).unique_id());
+}
+
+#[test]
+fn atom_is_unique_2() {
+    struct S(String);
+    static TEST_ATOM_1: Atom<Vec<S>> = Atom(|_| Vec::new());
+    static TEST_ATOM_2: Atom<Vec<String>> = Atom(|_| Vec::new());
+    assert_ne!((&TEST_ATOM_1).unique_id(), (&TEST_ATOM_2).unique_id());
 }
 }

+ 5 - 5
packages/fermi/src/atoms/atomfamily.rs

@@ -2,23 +2,23 @@ use crate::{AtomId, AtomRoot, Readable, Writable};
 use im_rc::HashMap as ImMap;
 use im_rc::HashMap as ImMap;
 
 
 pub struct AtomFamilyBuilder;
 pub struct AtomFamilyBuilder;
-pub type AtomFamily<K, V> = fn(AtomFamilyBuilder) -> ImMap<K, V>;
+pub struct AtomFamily<K, V>(pub fn(AtomFamilyBuilder) -> ImMap<K, V>);
 
 
-impl<K, V> Readable<ImMap<K, V>> for AtomFamily<K, V> {
+impl<K, V> Readable<ImMap<K, V>> for &'static AtomFamily<K, V> {
     fn read(&self, _root: AtomRoot) -> Option<ImMap<K, V>> {
     fn read(&self, _root: AtomRoot) -> Option<ImMap<K, V>> {
         todo!()
         todo!()
     }
     }
 
 
     fn init(&self) -> ImMap<K, V> {
     fn init(&self) -> ImMap<K, V> {
-        (*self)(AtomFamilyBuilder)
+        self.0(AtomFamilyBuilder)
     }
     }
 
 
     fn unique_id(&self) -> AtomId {
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        *self as *const AtomFamily<K, V> as *const ()
     }
     }
 }
 }
 
 
-impl<K, V> Writable<ImMap<K, V>> for AtomFamily<K, V> {
+impl<K, V> Writable<ImMap<K, V>> for &'static AtomFamily<K, V> {
     fn write(&self, _root: AtomRoot, _value: ImMap<K, V>) {
     fn write(&self, _root: AtomRoot, _value: ImMap<K, V>) {
         todo!()
         todo!()
     }
     }

+ 6 - 6
packages/fermi/src/atoms/atomref.rs

@@ -2,24 +2,24 @@ use crate::{AtomId, AtomRoot, Readable};
 use std::cell::RefCell;
 use std::cell::RefCell;
 
 
 pub struct AtomRefBuilder;
 pub struct AtomRefBuilder;
-pub type AtomRef<T> = fn(AtomRefBuilder) -> T;
+pub struct AtomRef<T>(pub fn(AtomRefBuilder) -> T);
 
 
-impl<V> Readable<RefCell<V>> for AtomRef<V> {
+impl<V> Readable<RefCell<V>> for &'static AtomRef<V> {
     fn read(&self, _root: AtomRoot) -> Option<RefCell<V>> {
     fn read(&self, _root: AtomRoot) -> Option<RefCell<V>> {
         todo!()
         todo!()
     }
     }
 
 
     fn init(&self) -> RefCell<V> {
     fn init(&self) -> RefCell<V> {
-        RefCell::new((*self)(AtomRefBuilder))
+        RefCell::new(self.0(AtomRefBuilder))
     }
     }
 
 
     fn unique_id(&self) -> AtomId {
     fn unique_id(&self) -> AtomId {
-        *self as *const ()
+        *self as *const AtomRef<V> as *const ()
     }
     }
 }
 }
 
 
 #[test]
 #[test]
 fn atom_compiles() {
 fn atom_compiles() {
-    static TEST_ATOM: AtomRef<Vec<String>> = |_| vec![];
-    dbg!(TEST_ATOM.init());
+    static TEST_ATOM: AtomRef<Vec<String>> = AtomRef(|_| vec![]);
+    dbg!((&TEST_ATOM).init());
 }
 }

+ 4 - 1
packages/fermi/src/hooks/atom_ref.rs

@@ -13,7 +13,10 @@ use std::{
 ///
 ///
 ///
 ///
 ///
 ///
-pub fn use_atom_ref<T: 'static>(cx: &ScopeState, atom: AtomRef<T>) -> &UseAtomRef<T> {
+pub fn use_atom_ref<'a, T: 'static>(
+    cx: &'a ScopeState,
+    atom: &'static AtomRef<T>,
+) -> &'a UseAtomRef<T> {
     let root = use_atom_root(cx);
     let root = use_atom_root(cx);
 
 
     &cx.use_hook(|| {
     &cx.use_hook(|| {

+ 1 - 1
packages/fermi/src/hooks/state.rs

@@ -19,7 +19,7 @@ use std::{
 /// static COUNT: Atom<u32> = |_| 0;
 /// static COUNT: Atom<u32> = |_| 0;
 ///
 ///
 /// fn Example(cx: Scope) -> Element {
 /// fn Example(cx: Scope) -> Element {
-///     let mut count = use_atom_state(cx, COUNT);
+///     let mut count = use_atom_state(cx, &COUNT);
 ///
 ///
 ///     cx.render(rsx! {
 ///     cx.render(rsx! {
 ///         div {
 ///         div {