Skip to content

Commit 4aa5605

Browse files
committed
Add infallible resource getters for WorldCell (#4104)
# Objective - Eliminate all `worldcell.get_resource().unwrap()` cases. - Provide helpful messages on panic. ## Solution - Adds infallible resource getters to `WorldCell`, mirroring `World`.
1 parent 989fb8a commit 4aa5605

File tree

8 files changed

+140
-74
lines changed

8 files changed

+140
-74
lines changed

crates/bevy_ecs/src/world/world_cell.rs

+96-16
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ impl<'w> WorldCell<'w> {
180180
}
181181
}
182182

183+
/// Gets a reference to the resource of the given type
183184
pub fn get_resource<T: Resource>(&self) -> Option<WorldBorrow<'_, T>> {
184185
let component_id = self.world.components.get_resource_id(TypeId::of::<T>())?;
185186
let resource_archetype = self.world.archetypes.resource();
@@ -192,6 +193,26 @@ impl<'w> WorldCell<'w> {
192193
))
193194
}
194195

196+
/// Gets a reference to the resource of the given type
197+
///
198+
/// # Panics
199+
///
200+
/// Panics if the resource does not exist. Use [`get_resource`](WorldCell::get_resource) instead
201+
/// if you want to handle this case.
202+
pub fn resource<T: Resource>(&self) -> WorldBorrow<'_, T> {
203+
match self.get_resource() {
204+
Some(x) => x,
205+
None => panic!(
206+
"Requested resource {} does not exist in the `World`.
207+
Did you forget to add it using `app.add_resource` / `app.init_resource`?
208+
Resources are also implicitly added via `app.add_event`,
209+
and can be added by plugins.",
210+
std::any::type_name::<T>()
211+
),
212+
}
213+
}
214+
215+
/// Gets a mutable reference to the resource of the given type
195216
pub fn get_resource_mut<T: Resource>(&self) -> Option<WorldBorrowMut<'_, T>> {
196217
let component_id = self.world.components.get_resource_id(TypeId::of::<T>())?;
197218
let resource_archetype = self.world.archetypes.resource();
@@ -207,7 +228,27 @@ impl<'w> WorldCell<'w> {
207228
))
208229
}
209230

210-
pub fn get_non_send<T: 'static>(&self) -> Option<WorldBorrow<'_, T>> {
231+
/// Gets a mutable reference to the resource of the given type
232+
///
233+
/// # Panics
234+
///
235+
/// Panics if the resource does not exist. Use [`get_resource_mut`](WorldCell::get_resource_mut)
236+
/// instead if you want to handle this case.
237+
pub fn resource_mut<T: Resource>(&self) -> WorldBorrowMut<'_, T> {
238+
match self.get_resource_mut() {
239+
Some(x) => x,
240+
None => panic!(
241+
"Requested resource {} does not exist in the `World`.
242+
Did you forget to add it using `app.add_resource` / `app.init_resource`?
243+
Resources are also implicitly added via `app.add_event`,
244+
and can be added by plugins.",
245+
std::any::type_name::<T>()
246+
),
247+
}
248+
}
249+
250+
/// Gets an immutable reference to the non-send resource of the given type, if it exists.
251+
pub fn get_non_send_resource<T: 'static>(&self) -> Option<WorldBorrow<'_, T>> {
211252
let component_id = self.world.components.get_resource_id(TypeId::of::<T>())?;
212253
let resource_archetype = self.world.archetypes.resource();
213254
let archetype_component_id = resource_archetype.get_archetype_component_id(component_id)?;
@@ -219,7 +260,27 @@ impl<'w> WorldCell<'w> {
219260
))
220261
}
221262

222-
pub fn get_non_send_mut<T: 'static>(&self) -> Option<WorldBorrowMut<'_, T>> {
263+
/// Gets an immutable reference to the non-send resource of the given type, if it exists.
264+
///
265+
/// # Panics
266+
///
267+
/// Panics if the resource does not exist. Use
268+
/// [`get_non_send_resource`](WorldCell::get_non_send_resource) instead if you want to handle
269+
/// this case.
270+
pub fn non_send_resource<T: 'static>(&self) -> WorldBorrow<'_, T> {
271+
match self.get_non_send_resource() {
272+
Some(x) => x,
273+
None => panic!(
274+
"Requested non-send resource {} does not exist in the `World`.
275+
Did you forget to add it using `app.add_non_send_resource` / `app.init_non_send_resource`?
276+
Non-send resources can also be be added by plugins.",
277+
std::any::type_name::<T>()
278+
),
279+
}
280+
}
281+
282+
/// Gets a mutable reference to the non-send resource of the given type, if it exists.
283+
pub fn get_non_send_resource_mut<T: 'static>(&self) -> Option<WorldBorrowMut<'_, T>> {
223284
let component_id = self.world.components.get_resource_id(TypeId::of::<T>())?;
224285
let resource_archetype = self.world.archetypes.resource();
225286
let archetype_component_id = resource_archetype.get_archetype_component_id(component_id)?;
@@ -233,6 +294,25 @@ impl<'w> WorldCell<'w> {
233294
self.access.clone(),
234295
))
235296
}
297+
298+
/// Gets a mutable reference to the non-send resource of the given type, if it exists.
299+
///
300+
/// # Panics
301+
///
302+
/// Panics if the resource does not exist. Use
303+
/// [`get_non_send_resource_mut`](WorldCell::get_non_send_resource_mut) instead if you want to
304+
/// handle this case.
305+
pub fn non_send_resource_mut<T: 'static>(&self) -> WorldBorrowMut<'_, T> {
306+
match self.get_non_send_resource_mut() {
307+
Some(x) => x,
308+
None => panic!(
309+
"Requested non-send resource {} does not exist in the `World`.
310+
Did you forget to add it using `app.add_non_send_resource` / `app.init_non_send_resource`?
311+
Non-send resources can also be be added by plugins.",
312+
std::any::type_name::<T>()
313+
),
314+
}
315+
}
236316
}
237317

238318
#[cfg(test)]
@@ -248,28 +328,28 @@ mod tests {
248328
world.insert_resource(1u64);
249329
let cell = world.cell();
250330
{
251-
let mut a = cell.get_resource_mut::<u32>().unwrap();
331+
let mut a = cell.resource_mut::<u32>();
252332
assert_eq!(1, *a);
253333
*a = 2;
254334
}
255335
{
256-
let a = cell.get_resource::<u32>().unwrap();
336+
let a = cell.resource::<u32>();
257337
assert_eq!(2, *a, "ensure access is dropped");
258338

259-
let b = cell.get_resource::<u32>().unwrap();
339+
let b = cell.resource::<u32>();
260340
assert_eq!(
261341
2, *b,
262342
"ensure multiple immutable accesses can occur at the same time"
263343
);
264344
}
265345
{
266-
let a = cell.get_resource_mut::<u32>().unwrap();
346+
let a = cell.resource_mut::<u32>();
267347
assert_eq!(
268348
2, *a,
269349
"ensure both immutable accesses are dropped, enabling a new mutable access"
270350
);
271351

272-
let b = cell.get_resource::<u64>().unwrap();
352+
let b = cell.resource::<u64>();
273353
assert_eq!(
274354
1, *b,
275355
"ensure multiple non-conflicting mutable accesses can occur at the same time"
@@ -284,7 +364,7 @@ mod tests {
284364
{
285365
let cell = world.cell();
286366
{
287-
let mut a = cell.get_resource_mut::<u32>().unwrap();
367+
let mut a = cell.resource_mut::<u32>();
288368
assert_eq!(1, *a);
289369
*a = 2;
290370
}
@@ -315,8 +395,8 @@ mod tests {
315395
let mut world = World::default();
316396
world.insert_resource(1u32);
317397
let cell = world.cell();
318-
let _value_a = cell.get_resource_mut::<u32>().unwrap();
319-
let _value_b = cell.get_resource_mut::<u32>().unwrap();
398+
let _value_a = cell.resource_mut::<u32>();
399+
let _value_b = cell.resource_mut::<u32>();
320400
}
321401

322402
#[test]
@@ -325,8 +405,8 @@ mod tests {
325405
let mut world = World::default();
326406
world.insert_resource(1u32);
327407
let cell = world.cell();
328-
let _value_a = cell.get_resource::<u32>().unwrap();
329-
let _value_b = cell.get_resource_mut::<u32>().unwrap();
408+
let _value_a = cell.resource::<u32>();
409+
let _value_b = cell.resource_mut::<u32>();
330410
}
331411

332412
#[test]
@@ -335,8 +415,8 @@ mod tests {
335415
let mut world = World::default();
336416
world.insert_resource(1u32);
337417
let cell = world.cell();
338-
let _value_a = cell.get_resource_mut::<u32>().unwrap();
339-
let _value_b = cell.get_resource::<u32>().unwrap();
418+
let _value_a = cell.resource_mut::<u32>();
419+
let _value_b = cell.resource::<u32>();
340420
}
341421

342422
#[test]
@@ -345,7 +425,7 @@ mod tests {
345425
let mut world = World::default();
346426
world.insert_resource(1u32);
347427
let cell = world.cell();
348-
let _value_a = cell.get_resource_mut::<u32>().unwrap();
349-
let _value_b = cell.get_resource::<u32>().unwrap();
428+
let _value_a = cell.resource_mut::<u32>();
429+
let _value_b = cell.resource::<u32>();
350430
}
351431
}

crates/bevy_pbr/src/render/light.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ pub struct ShadowPipeline {
236236
impl FromWorld for ShadowPipeline {
237237
fn from_world(world: &mut World) -> Self {
238238
let world = world.cell();
239-
let render_device = world.get_resource::<RenderDevice>().unwrap();
239+
let render_device = world.resource::<RenderDevice>();
240240

241241
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
242242
entries: &[
@@ -255,7 +255,7 @@ impl FromWorld for ShadowPipeline {
255255
label: Some("shadow_view_layout"),
256256
});
257257

258-
let mesh_pipeline = world.get_resource::<MeshPipeline>().unwrap();
258+
let mesh_pipeline = world.resource::<MeshPipeline>();
259259
let skinned_mesh_layout = mesh_pipeline.skinned_mesh_layout.clone();
260260

261261
ShadowPipeline {

crates/bevy_sprite/src/render/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub struct SpritePipeline {
3939
impl FromWorld for SpritePipeline {
4040
fn from_world(world: &mut World) -> Self {
4141
let world = world.cell();
42-
let render_device = world.get_resource::<RenderDevice>().unwrap();
42+
let render_device = world.resource::<RenderDevice>();
4343

4444
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
4545
entries: &[BindGroupLayoutEntry {

crates/bevy_ui/src/render/pipeline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub struct UiPipeline {
1414
impl FromWorld for UiPipeline {
1515
fn from_world(world: &mut World) -> Self {
1616
let world = world.cell();
17-
let render_device = world.get_resource::<RenderDevice>().unwrap();
17+
let render_device = world.resource::<RenderDevice>();
1818

1919
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
2020
entries: &[BindGroupLayoutEntry {

0 commit comments

Comments
 (0)