Experiment with call syntax only working for copy types
This commit is contained in:
19 files changed
+52
-76
No files matched your search
@@ -22,7 +22,7 @@ fn app() -> Element {
|
|||||||
let val = use_signal(|| String::from("0"));
|
let val = use_signal(|| String::from("0"));
|
||||||
|
|
||||||
let input_digit = move |num: u8| {
|
let input_digit = move |num: u8| {
|
||||||
if *val() == "0" {
|
if val.cloned() == "0" {
|
||||||
val.set(String::new());
|
val.set(String::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ fn app() -> Element {
|
|||||||
class: "calculator-key key-percent",
|
class: "calculator-key key-percent",
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
val.set(
|
val.set(
|
||||||
format!("{}", calc_val(val().as_str()) / 100.0)
|
format!("{}", calc_val(val.cloned().as_str()) / 100.0)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
"%"
|
"%"
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,7 @@ fn app() -> Element {
|
|||||||
let open_compose_window = move |evt: MouseEvent| {
|
let open_compose_window = move |evt: MouseEvent| {
|
||||||
let tx = handle.tx();
|
let tx = handle.tx();
|
||||||
dioxus_desktop::window().new_window(
|
dioxus_desktop::window().new_window(
|
||||||
VirtualDom::new_with_props(compose, Rc::new(move |s| tx.unbounded_send(s))),
|
VirtualDom::new_with_props(compose, Rc::new(move |s| tx.unbounded_send(s).unwrap())),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -50,7 +50,7 @@ fn compose(send: Rc<dyn Fn(String)>) -> Element {
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
send(user_input.get().clone());
|
send(user_input.cloned());
|
||||||
dioxus_desktop::window().close();
|
dioxus_desktop::window().close();
|
||||||
},
|
},
|
||||||
"Click to send"
|
"Click to send"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ fn app() -> Element {
|
|||||||
|
|
||||||
use_future(move || async move {
|
use_future(move || async move {
|
||||||
let mut focused = 0;
|
let mut focused = 0;
|
||||||
if *running() {
|
if running() {
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||||
if let Some(element) = elements.with(|f| f.get(focused).cloned()) {
|
if let Some(element) = elements.with(|f| f.get(focused).cloned()) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ fn app() -> Element {
|
|||||||
div {
|
div {
|
||||||
button { onclick: move |_| disabled.toggle(),
|
button { onclick: move |_| disabled.toggle(),
|
||||||
"click to "
|
"click to "
|
||||||
if *disabled() { "enable" } else { "disable" }
|
if disabled() { "enable" } else { "disable" }
|
||||||
" the lower button"
|
" the lower button"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -33,7 +33,9 @@ fn app() -> Element {
|
|||||||
Some(resp) => rsx! {
|
Some(resp) => rsx! {
|
||||||
h1 { "Select a dog breed!" }
|
h1 { "Select a dog breed!" }
|
||||||
div { height: "500px", display: "flex",
|
div { height: "500px", display: "flex",
|
||||||
ul { flex: "50%", {breed_list} }
|
ul { flex: "50%", {breed_list.value().cloned().unwrap_or_else(|| rsx! {
|
||||||
|
"loading breeds..."
|
||||||
|
})} }
|
||||||
div { flex: "50%", BreedPic { breed } }
|
div { flex: "50%", BreedPic { breed } }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
//! This example shows that you can place heavy work on the main thread, and then
|
|
||||||
//!
|
|
||||||
//! You *should* be using `tokio::spawn_blocking` instead.
|
|
||||||
//!
|
|
||||||
//! Your app runs in an async runtime (Tokio), so you should avoid blocking
|
|
||||||
//! the rendering of the VirtualDom.
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
dioxus_desktop::launch(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn app() -> Element {
|
|
||||||
// This is discouraged
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(2_000));
|
|
||||||
|
|
||||||
// This is suggested
|
|
||||||
tokio::task::spawn_blocking(move || {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(2_000));
|
|
||||||
});
|
|
||||||
|
|
||||||
rsx! {
|
|
||||||
div { "Hello, world!" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ fn app() -> Element {
|
|||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
h1 { "Login" }
|
h1 { "Login" }
|
||||||
form { onsubmit: onsubmit,
|
form { onsubmit,
|
||||||
input { r#type: "text", id: "username", name: "username" }
|
input { r#type: "text", id: "username", name: "username" }
|
||||||
label { "Username" }
|
label { "Username" }
|
||||||
br {}
|
br {}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ fn app() -> Element {
|
|||||||
height: "50%",
|
height: "50%",
|
||||||
background_color: "red",
|
background_color: "red",
|
||||||
onmounted: move |cx| div_element.set(Some(cx.inner().clone())),
|
onmounted: move |cx| div_element.set(Some(cx.inner().clone())),
|
||||||
"This element is {*dimensions():?}"
|
"This element is {dimensions():?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn app() -> Element {
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
onclick: move |_| async move {
|
onclick: move |_| async move {
|
||||||
if let Some(header) = header_element.read().as_ref().cloned() {
|
if let Some(header) = header_element.cloned() {
|
||||||
let _ = header.scroll_to(ScrollBehavior::Smooth).await;
|
let _ = header.scroll_to(ScrollBehavior::Smooth).await;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+3
-3
@@ -14,7 +14,7 @@ fn app() -> Element {
|
|||||||
// Signals are backed by a runtime that is designed to deeply integrate with Dioxus apps
|
// Signals are backed by a runtime that is designed to deeply integrate with Dioxus apps
|
||||||
use_future(|| async move {
|
use_future(|| async move {
|
||||||
loop {
|
loop {
|
||||||
if running.value() {
|
if running.cloned() {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
tokio::time::sleep(Duration::from_millis(400)).await;
|
tokio::time::sleep(Duration::from_millis(400)).await;
|
||||||
@@ -26,11 +26,11 @@ fn app() -> Element {
|
|||||||
button { onclick: move |_| count += 1, "Up high!" }
|
button { onclick: move |_| count += 1, "Up high!" }
|
||||||
button { onclick: move |_| count -= 1, "Down low!" }
|
button { onclick: move |_| count -= 1, "Down low!" }
|
||||||
button { onclick: move |_| running.toggle(), "Toggle counter" }
|
button { onclick: move |_| running.toggle(), "Toggle counter" }
|
||||||
button { onclick: move |_| saved_values.push(count.value().to_string()), "Save this value" }
|
button { onclick: move |_| saved_values.push(count.cloned().to_string()), "Save this value" }
|
||||||
button { onclick: move |_| saved_values.write().clear(), "Clear saved values" }
|
button { onclick: move |_| saved_values.write().clear(), "Clear saved values" }
|
||||||
|
|
||||||
// We can do boolean operations on the current signal value
|
// We can do boolean operations on the current signal value
|
||||||
if count.value() > 5 {
|
if count() > 5 {
|
||||||
h2 { "High five!" }
|
h2 { "High five!" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -1,8 +1,7 @@
|
|||||||
use dioxus::{dioxus_core::NoOpMutations, prelude::*};
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
let mut dom = VirtualDom::prebuilt(app);
|
||||||
let _ = dom.rebuild(&mut NoOpMutations);
|
|
||||||
let html = dioxus_ssr::render(&dom);
|
let html = dioxus_ssr::render(&dom);
|
||||||
|
|
||||||
println!("{}", html);
|
println!("{}", html);
|
||||||
|
|||||||
+2
-3
@@ -2,12 +2,11 @@
|
|||||||
//!
|
//!
|
||||||
//! This example shows how we can render the Dioxus Virtualdom using SSR.
|
//! This example shows how we can render the Dioxus Virtualdom using SSR.
|
||||||
|
|
||||||
use dioxus::{core::NoOpMutations, prelude::*};
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// We can render VirtualDoms
|
// We can render VirtualDoms
|
||||||
let mut vdom = VirtualDom::new(app);
|
let mut vdom = VirtualDom::prebuilt(app);
|
||||||
let _ = vdom.rebuild(&mut NoOpMutations);
|
|
||||||
println!("{}", dioxus_ssr::render(&vdom));
|
println!("{}", dioxus_ssr::render(&vdom));
|
||||||
|
|
||||||
// Or we can render rsx! calls themselves
|
// Or we can render rsx! calls themselves
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ fn Dice() -> Element {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let value = use_signal(|| 5);
|
let value = use_signal(|| 5);
|
||||||
let active_dots = use_selector(move || &DOTS_FOR_VALUE[(*value() - 1) as usize]);
|
let active_dots = use_selector(move || &DOTS_FOR_VALUE[(value() - 1) as usize]);
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
svg {
|
svg {
|
||||||
|
|||||||
+14
-13
@@ -26,12 +26,13 @@ pub fn app() -> Element {
|
|||||||
let filter = use_signal(|| FilterState::All);
|
let filter = use_signal(|| FilterState::All);
|
||||||
|
|
||||||
let active_todo_count =
|
let active_todo_count =
|
||||||
use_selector(move || todos().values().filter(|item| !item.checked).count());
|
use_selector(move || todos.read().values().filter(|item| !item.checked).count());
|
||||||
|
|
||||||
let filtered_todos = use_selector(move || {
|
let filtered_todos = use_selector(move || {
|
||||||
let mut filtered_todos = todos()
|
let mut filtered_todos = todos
|
||||||
|
.read()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, item)| match *filter() {
|
.filter(|(_, item)| match filter() {
|
||||||
FilterState::All => true,
|
FilterState::All => true,
|
||||||
FilterState::Active => !item.checked,
|
FilterState::Active => !item.checked,
|
||||||
FilterState::Completed => item.checked,
|
FilterState::Completed => item.checked,
|
||||||
@@ -49,7 +50,7 @@ pub fn app() -> Element {
|
|||||||
style { {include_str!("./assets/todomvc.css")} }
|
style { {include_str!("./assets/todomvc.css")} }
|
||||||
TodoHeader { todos }
|
TodoHeader { todos }
|
||||||
section { class: "main",
|
section { class: "main",
|
||||||
if !todos().is_empty() {
|
if !todos.read().is_empty() {
|
||||||
input {
|
input {
|
||||||
id: "toggle-all",
|
id: "toggle-all",
|
||||||
class: "toggle-all",
|
class: "toggle-all",
|
||||||
@@ -69,7 +70,7 @@ pub fn app() -> Element {
|
|||||||
TodoEntry { key: "{id}", id, todos }
|
TodoEntry { key: "{id}", id, todos }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !todos().is_empty() {
|
if !todos.read().is_empty() {
|
||||||
ListFooter { active_todo_count, todos, filter }
|
ListFooter { active_todo_count, todos, filter }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,8 +85,8 @@ pub fn TodoHeader(todos: Signal<HashMap<u32, TodoItem>>) -> Element {
|
|||||||
let mut todo_id = use_signal(|| 0);
|
let mut todo_id = use_signal(|| 0);
|
||||||
|
|
||||||
let onkeydown = move |evt: KeyboardEvent| {
|
let onkeydown = move |evt: KeyboardEvent| {
|
||||||
if evt.key() == Key::Enter && !draft().is_empty() {
|
if evt.key() == Key::Enter && !draft.read().is_empty() {
|
||||||
let id = *todo_id();
|
let id = todo_id();
|
||||||
let todo = TodoItem {
|
let todo = TodoItem {
|
||||||
id,
|
id,
|
||||||
checked: false,
|
checked: false,
|
||||||
@@ -115,11 +116,11 @@ pub fn TodoHeader(todos: Signal<HashMap<u32, TodoItem>>) -> Element {
|
|||||||
#[component]
|
#[component]
|
||||||
pub fn TodoEntry(todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
|
pub fn TodoEntry(todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
|
||||||
let is_editing = use_signal(|| false);
|
let is_editing = use_signal(|| false);
|
||||||
let checked = use_selector(move || todos().get(&id).unwrap().checked);
|
let checked = use_selector(move || todos.read().get(&id).unwrap().checked);
|
||||||
let contents = use_selector(move || todos().get(&id).unwrap().contents.clone());
|
let contents = use_selector(move || todos.read().get(&id).unwrap().contents.clone());
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
li { class: if *checked() { "completed" }, class: if *is_editing() { "editing"},
|
li { class: if checked() { "completed" }, class: if is_editing() { "editing"},
|
||||||
div { class: "view",
|
div { class: "view",
|
||||||
input {
|
input {
|
||||||
class: "toggle",
|
class: "toggle",
|
||||||
@@ -140,7 +141,7 @@ pub fn TodoEntry(todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
|
|||||||
prevent_default: "onclick"
|
prevent_default: "onclick"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if *is_editing() {
|
if is_editing() {
|
||||||
input {
|
input {
|
||||||
class: "edit",
|
class: "edit",
|
||||||
value: "{contents}",
|
value: "{contents}",
|
||||||
@@ -165,7 +166,7 @@ pub fn ListFooter(
|
|||||||
active_todo_count: ReadOnlySignal<usize>,
|
active_todo_count: ReadOnlySignal<usize>,
|
||||||
filter: Signal<FilterState>,
|
filter: Signal<FilterState>,
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let show_clear_completed = use_selector(move || todos().values().any(|todo| todo.checked));
|
let show_clear_completed = use_selector(move || todos.read().values().any(|todo| todo.checked));
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
footer { class: "footer",
|
footer { class: "footer",
|
||||||
@@ -188,7 +189,7 @@ pub fn ListFooter(
|
|||||||
li {
|
li {
|
||||||
a {
|
a {
|
||||||
href: url,
|
href: url,
|
||||||
class: if *filter() == state { "selected" },
|
class: if filter() == state { "selected" },
|
||||||
onclick: move |_| filter.set(state),
|
onclick: move |_| filter.set(state),
|
||||||
prevent_default: "onclick",
|
prevent_default: "onclick",
|
||||||
{state_text}
|
{state_text}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ fn app() -> Element {
|
|||||||
class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
|
class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
|
||||||
onmousedown: |evt| evt.stop_propagation(),
|
onmousedown: |evt| evt.stop_propagation(),
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
window().set_fullscreen(!*fullscreen());
|
window().set_fullscreen(!fullscreen());
|
||||||
window().set_resizable(*fullscreen());
|
window().set_resizable(fullscreen());
|
||||||
fullscreen.toggle();
|
fullscreen.toggle();
|
||||||
},
|
},
|
||||||
"Fullscreen"
|
"Fullscreen"
|
||||||
@@ -58,7 +58,7 @@ fn app() -> Element {
|
|||||||
class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
||||||
onmousedown: |evt| evt.stop_propagation(),
|
onmousedown: |evt| evt.stop_propagation(),
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
window().set_always_on_top(!*always_on_top());
|
window().set_always_on_top(!always_on_top());
|
||||||
always_on_top.toggle();
|
always_on_top.toggle();
|
||||||
},
|
},
|
||||||
"Always On Top"
|
"Always On Top"
|
||||||
@@ -69,7 +69,7 @@ fn app() -> Element {
|
|||||||
class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
|
||||||
onmousedown: |evt| evt.stop_propagation(),
|
onmousedown: |evt| evt.stop_propagation(),
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
window().set_decorations(!*decorations());
|
window().set_decorations(!decorations());
|
||||||
decorations.toggle();
|
decorations.toggle();
|
||||||
},
|
},
|
||||||
"Set Decorations"
|
"Set Decorations"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ fn app() -> Element {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
flex_direction: "column",
|
flex_direction: "column",
|
||||||
align_items: "center",
|
align_items: "center",
|
||||||
if *focused() {
|
if focused() {
|
||||||
"This window is focused!"
|
"This window is focused!"
|
||||||
} else {
|
} else {
|
||||||
"This window is not focused!"
|
"This window is not focused!"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fn app() -> Element {
|
|||||||
|
|
||||||
let local_state = use_signal(|| 0);
|
let local_state = use_signal(|| 0);
|
||||||
let computed = use_selector_with_dependencies((local_state.get(),), move |(local_state,)| {
|
let computed = use_selector_with_dependencies((local_state.get(),), move |(local_state,)| {
|
||||||
local_state * 2 + signal.value()
|
local_state * 2 + signal.cloned()
|
||||||
});
|
});
|
||||||
println!("Running app");
|
println!("Running app");
|
||||||
|
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ impl<T: Clone + 'static> Signal<T> {
|
|||||||
/// Get the current value of the signal. This will subscribe the current scope to the 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.
|
/// If the signal has been dropped, this will panic.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn value(&self) -> T {
|
pub fn cloned(&self) -> T {
|
||||||
self.read().clone()
|
self.read().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +338,7 @@ impl<T: Clone + 'static> Signal<T> {
|
|||||||
impl Signal<bool> {
|
impl Signal<bool> {
|
||||||
/// Invert the boolean value of the signal. This will trigger an update on all subscribers.
|
/// Invert the boolean value of the signal. This will trigger an update on all subscribers.
|
||||||
pub fn toggle(&self) {
|
pub fn toggle(&self) {
|
||||||
self.set(!self.value());
|
self.set(!self.cloned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,8 +348,8 @@ impl<T: 'static> PartialEq for Signal<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Deref for Signal<T> {
|
impl<T: Copy> Deref for Signal<T> {
|
||||||
type Target = dyn Fn() -> GenerationalRef<T>;
|
type Target = dyn Fn() -> T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
// https://github.com/dtolnay/case-studies/tree/master/callable-types
|
// https://github.com/dtolnay/case-studies/tree/master/callable-types
|
||||||
@@ -357,7 +357,10 @@ impl<T> Deref for Signal<T> {
|
|||||||
// First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
|
// First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
|
||||||
let uninit_callable = MaybeUninit::<Self>::uninit();
|
let uninit_callable = MaybeUninit::<Self>::uninit();
|
||||||
// Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
|
// Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
|
||||||
let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() });
|
let uninit_closure = move || {
|
||||||
|
let res = Self::read(unsafe { &*uninit_callable.as_ptr() });
|
||||||
|
res.clone()
|
||||||
|
};
|
||||||
|
|
||||||
// Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
|
// Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
|
||||||
let size_of_closure = std::mem::size_of_val(&uninit_closure);
|
let size_of_closure = std::mem::size_of_val(&uninit_closure);
|
||||||
@@ -483,8 +486,8 @@ impl<T: 'static> PartialEq for ReadOnlySignal<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Deref for ReadOnlySignal<T> {
|
impl<T: Copy> Deref for ReadOnlySignal<T> {
|
||||||
type Target = dyn Fn() -> GenerationalRef<T>;
|
type Target = dyn Fn() -> T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
// https://github.com/dtolnay/case-studies/tree/master/callable-types
|
// https://github.com/dtolnay/case-studies/tree/master/callable-types
|
||||||
@@ -492,7 +495,7 @@ impl<T> Deref for ReadOnlySignal<T> {
|
|||||||
// First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
|
// First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
|
||||||
let uninit_callable = MaybeUninit::<Self>::uninit();
|
let uninit_callable = MaybeUninit::<Self>::uninit();
|
||||||
// Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
|
// Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
|
||||||
let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() });
|
let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }).clone();
|
||||||
|
|
||||||
// Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
|
// Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
|
||||||
let size_of_closure = std::mem::size_of_val(&uninit_closure);
|
let size_of_closure = std::mem::size_of_val(&uninit_closure);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fn memos_rerun() {
|
|||||||
selector(move || {
|
selector(move || {
|
||||||
counter.borrow_mut().effect += 1;
|
counter.borrow_mut().effect += 1;
|
||||||
println!("Signal: {:?}", signal);
|
println!("Signal: {:?}", signal);
|
||||||
signal.value()
|
signal.cloned()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
assert_eq!(memo.value(), 0);
|
assert_eq!(memo.value(), 0);
|
||||||
|
|||||||
Reference in new issue
Block a user