Repository: bevyengine/bevy
File: crates/bevy_ecs/src/world/mod.rs (Rust)

Code before:
    /// ```
    #[track_caller]
    pub fn resource_scope<R: Resource, U>(&mut self, f: impl FnOnce(&mut World, Mut<R>) -> U) -> U {
        self.try_resource_scope(f)
            .unwrap_or_else(|| panic!("resource does not exist: {}", DebugName::type_name::<R>()))
    }

    /// Temporarily removes the requested resource from this [`World`] if it exists, runs custom user code,
    /// then re-adds the resource before returning. Returns `None` if the resource does not exist in this [`World`].
    ///
    /// This enables safe simultaneous mutable access to both a resource and the rest of the [`World`].
    /// For more complex access patterns, consider using [`SystemState`](crate::system::SystemState).
    ///
    /// See also [`resource_scope`](Self::resource_scope).
    pub fn try_resource_scope<R: Resource, U>(
        &mut self,
        f: impl FnOnce(&mut World, Mut<R>) -> U,
    ) -> Option<U> {
        let last_change_tick = self.last_change_tick();
        let change_tick = self.change_tick();

        let component_id = self.components.get_valid_resource_id(TypeId::of::<R>())?;
        let (ptr, ticks, caller) = self.storages.resources.get_mut(component_id)?.remove()?;

        // Read the value onto the stack to avoid potential mut aliasing.
        // SAFETY: `ptr` was obtained from the TypeId of `R`.
        let value = unsafe { ptr.read::<R>() };

        // type used to manage reinserting the resource at the end of the scope. use of a drop impl means that
        // the resource is inserted even if the user-provided closure unwinds.
        // this facilitates localized panic recovery and makes app shutdown in response to a panic more graceful
        // by avoiding knock-on errors.
        struct ReinsertGuard<'a, R> {
            world: &'a mut World,
            component_id: ComponentId,
            value: ManuallyDrop<R>,
            ticks: ComponentTicks,
            caller: MaybeLocation,
            was_successful: &'a mut bool,
        }
        impl<R> Drop for ReinsertGuard<'_, R> {
            fn drop(&mut self) {
                // take ownership of the value first so it'll get dropped if we return early
                // SAFETY: drop semantics ensure that `self.value` will never be accessed again after this call
                let value = unsafe { ManuallyDrop::take(&mut self.value) };

                let Some(resource_data) = self.world.storages.resources.get_mut(self.component_id)
                else {
                    return;
                };


Review comment (suggestion):
If I’m understanding your changes correctly, `try_resource_scope` now always returns `Some(result)`.  I understand not changing the return value to `U` if it would be an invasive change, but I think the doc comment for this function could be updated since it currently says "Returns `None` if the resource does not exist in this [`World`]." Probably makes sense to remove the line at least? Not tied to it though.

Code after:
    /// ```
    ///
    /// # Note
    ///
    /// If the world's resource metadata is cleared within the scope, such as by calling
    /// [`World::clear_resources`] or [`World::clear_all`], the resource will *not* be re-inserted
    /// at the end of the scope.
    #[track_caller]
    pub fn resource_scope<R: Resource, U>(&mut self, f: impl FnOnce(&mut World, Mut<R>) -> U) -> U {
        self.try_resource_scope(f)
            .unwrap_or_else(|| panic!("resource does not exist: {}", DebugName::type_name::<R>()))
    }

    /// Temporarily removes the requested resource from this [`World`] if it exists, runs custom user code,
    /// then re-adds the resource before returning. Returns `None` if the resource does not exist in this [`World`].
    ///
    /// This enables safe simultaneous mutable access to both a resource and the rest of the [`World`].
    /// For more complex access patterns, consider using [`SystemState`](crate::system::SystemState).
    ///
    /// See also [`resource_scope`](Self::resource_scope).
    ///
    /// # Note
    ///
    /// If the world's resource metadata is cleared within the scope, such as by calling
    /// [`World::clear_resources`] or [`World::clear_all`], the resource will *not* be re-inserted
    /// at the end of the scope.
    pub fn try_resource_scope<R: Resource, U>(
        &mut self,
        f: impl FnOnce(&mut World, Mut<R>) -> U,
    ) -> Option<U> {
        let last_change_tick = self.last_change_tick();
        let change_tick = self.change_tick();

        let component_id = self.components.get_valid_resource_id(TypeId::of::<R>())?;
        let (ptr, ticks, caller) = self.storages.resources.get_mut(component_id)?.remove()?;

        // Read the value onto the stack to avoid potential mut aliasing.
        // SAFETY: `ptr` was obtained from the TypeId of `R`.
        let value = unsafe { ptr.read::<R>() };

        // type used to manage reinserting the resource at the end of the scope. use of a drop impl means that
        // the resource is inserted even if the user-provided closure unwinds.
        // this facilitates localized panic recovery and makes app shutdown in response to a panic more graceful
        // by avoiding knock-on errors.
        struct ReinsertGuard<'a, R> {
            world: &'a mut World,
            component_id: ComponentId,
            value: ManuallyDrop<R>,
            ticks: ComponentTicks,
            caller: MaybeLocation,
        }