I have my own framework crate that stores all of its nodes inside one vector as a trait object to be allocated/read/written by application logic and engine.
I have trouble to understand what Rust does not understand with this write function for such node:
pub fn write
<
T: NodeEvent + 'static,
TFunction: FnOnce(&mut T)
>
(
handle: &Handle<T>,
function: TFunction
)
{
let guard_allocations = NODE_ALLOCATIONS.read().unwrap();
let mut node_guard = guard_allocations.get(handle.index.0).unwrap().write().unwrap();
let node_any: &mut dyn Any = &mut &mut*node_guard.node as &mut dyn Any;
let concrete_data = node_any.downcast_mut::<T>().unwrap();
function(concrete_data);
}
It says:
error[E0597]:
guard_allocations
does not live long enough
--> src/lib.rs:1098:26
|
1098 | let mut node_guard = guard_allocations.get(handle.index.0).unwrap().write().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
1099 | let node_any: &mut dyn Any = &mut &mut*node_guard.node as &mut dyn Any;
| ------------------------- cast requires thatguard_allocations
is borrowed for'static
...
1102 | }
| -guard_allocations
dropped here while still borrowed
let guard_allocations is type
static NODE_ALLOCATIONS: RwLock<Vec<RwLock<Allocation>>> = RwLock::new(Vec::new());
Allocation is type
struct Allocation
{
id: AllocationID,
node: Box<dyn NodeEvent + Send + Sync>
}
How can anything inside a function live not enough for something outside a function like static NODE_ALLOCATIONS? Especially behind a guard?
Bad Working Solution
I need Any trait so that I can do a downcast_mut() to the concrete_data of that node and I get that via custom any() and any_mut() via the NodeEvent trait.
Which means every time I define a new node inside the app logic for the game engine framework like say Door or for the engine like say MeshInstance. I would have to also implement these two very simple any functions all the time. Rust does not allow any additional traits inside that trait object unless it is some auto trait. And a trait default for them causes a sized issue with the default definition or when calling:
error: the `any_mut` method cannot be invoked on a trait object
--> /media/omnissiah/MyData/_NerlinGames/NerhimUniverse/Nerhim/nokden/src/lib.rs:1202:49
|
1202 | let concrete_data = node_guard.node.any_mut().downcast_mut::<T>().unwrap();
| ^^^^^^^
...
1306 | -> &mut dyn Any where Self: Sized
|
Previously used bad solution. Just define for every node outside the framework crate instead of using their trait default:
impl
NodeEvent
for [NodeType] // Players, Doors, Meshes, Audio, etc.
{
fn console() ...
fn filing() ...
fn any
(
&self,
)
-> &dyn Any
{
self
}
fn any_mut
(
&mut self,
)
-> &mut dyn Any
{
self
}
}
It is not the end of the world having to do that. But it is very stupid since that code never changes and always just returns self as Any.
Wrapping into unsafe block to shut-up the compiler also does not seem to work.
As a side note. The nodes have to be stored in a static manner so that they are readable by the Drop trait. It essentially does garbage collection that way. When a handle for a node is dropped the framework knows that the node allocation for that handle also needs freeing.