bones
bones copied to clipboard
Panic: if `get_resource` is called (provides None if missing), then `init_resource`, get a panic
world.get_resource does this:
#[track_caller]
pub fn get<T: HasSchema>(&self) -> Option<Ref<T>> {
let b = self.untyped.get(T::schema()).borrow();
if b.is_some() {
Some(Ref::map(b, |b| unsafe {
b.as_ref().unwrap().as_ref().cast_into_unchecked()
}))
} else {
None
}
}
self.untyped.get() This inserts the the schema id into OnceMap, with contents being empty.
init_resource does:
pub fn init_resource<R: HasSchema + FromWorld>(&mut self) -> RefMut<R> {
if unlikely(!self.resources.contains::<R>()) {
let value = R::from_world(self);
self.resources.insert(value);
}
self.resource_mut()
}
and contains only checks if ID is contained - not if resource has a value. This skips the init branch, and only calls self.resource_mut which panics on missing resource value.
This is the only place in bones that contains is used, I think we should update this to check if the resource has a value, and not just ID entry in map. This is what I would expect when using the function as well.
Seems to fix if change Resources::contains to do:
pub fn contains<T: HasSchema>(&self) -> bool {
self.untyped.contains(T::schema().id())
}
instead of:
pub fn contains<T: HasSchema>(&self) -> bool {
self.untyped.resources.contains_key(&T::schema().id())
}