dioxus_signals/
warnings.rs1use warnings::warning;
4
5#[warning]
7pub fn copy_value_hoisted<T: 'static, S: generational_box::Storage<T> + 'static>(
8 value: &crate::CopyValue<T, S>,
9 caller: &'static std::panic::Location<'static>,
10) {
11 let origin_scope = value.origin_scope;
12 let Some(rt) = dioxus_core::Runtime::try_current() else {
13 return;
14 };
15
16 if let Some(current_scope) = rt.try_current_scope_id() {
17 if origin_scope == current_scope || rt.is_descendant_of(current_scope, origin_scope) {
19 return;
20 }
21 let create_location = value.value.created_at().unwrap();
22 let broken_example = include_str!("../docs/hoist/error.rs");
23 let fixed_example = include_str!("../docs/hoist/fixed_list.rs");
24
25 tracing::warn!(
27 r#"A Copy Value created in {origin_scope:?} (at {create_location}). It will be dropped when that scope is dropped, but it was used in {current_scope:?} (at {caller}) which is not a descendant of the owning scope.
28This may cause reads or writes to fail because the value is dropped while it still held.
29
30Help:
31Copy values (like CopyValue, Signal, Memo, and Resource) are owned by the scope they are created in. If you use the value in a scope that may be dropped after the origin scope,
32it is very easy to use the value after it has been dropped. To fix this, you can move the value to the parent of all of the scopes that it is used in.
33
34Broken example ❌:
35```rust
36{broken_example}
37```
38
39Fixed example ✅:
40```rust
41{fixed_example}
42```"#
43 );
44 }
45}
46
47#[test]
49#[allow(unused)]
50fn hoist() {
51 mod broken {
52 use dioxus::prelude::*;
53 include!("../docs/hoist/error.rs");
54 }
55 mod fixed {
56 use dioxus::prelude::*;
57 include!("../docs/hoist/fixed_list.rs");
58 }
59}