Skip to content
4 changes: 4 additions & 0 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
#(#fields: #field_locals,)*
}
}

fn world_access_level() -> #path::system::WorldAccessLevel {
<#fields_alias::<'_, '_, #punctuated_generic_idents> as #path::system::SystemParam>::world_access_level()
}
}

// Safety: Each field is `ReadOnlySystemParam`, so this can only read from the `World`
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_ecs/src/removal_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
event::{Event, EventCursor, EventId, EventIterator, EventIteratorWithId, Events},
prelude::Local,
storage::SparseSet,
system::{ReadOnlySystemParam, SystemMeta, SystemParam},
system::{ReadOnlySystemParam, SystemMeta, SystemParam, WorldAccessLevel},
world::{unsafe_world_cell::UnsafeWorldCell, World},
};

Expand Down Expand Up @@ -266,4 +266,8 @@ unsafe impl<'a> SystemParam for &'a RemovedComponentEvents {
) -> Self::Item<'w, 's> {
world.removed_components()
}

fn world_access_level() -> WorldAccessLevel {
WorldAccessLevel::Shared
}
}
19 changes: 1 addition & 18 deletions crates/bevy_ecs/src/schedule/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ pub use bevy_ecs_macros::{ScheduleLabel, SystemSet};
use crate::{
define_label,
intern::Interned,
system::{
ExclusiveFunctionSystem, ExclusiveSystemParamFunction, FunctionSystem,
IsExclusiveFunctionSystem, IsFunctionSystem, SystemParamFunction,
},
system::{FunctionSystem, IsFunctionSystem, SystemParamFunction},
};

define_label!(
Expand Down Expand Up @@ -200,20 +197,6 @@ where
}
}

// exclusive systems
impl<Marker, F> IntoSystemSet<(IsExclusiveFunctionSystem, Marker)> for F
where
Marker: 'static,
F: ExclusiveSystemParamFunction<Marker>,
{
type Set = SystemTypeSet<ExclusiveFunctionSystem<Marker, F>>;

#[inline]
fn into_system_set(self) -> Self::Set {
SystemTypeSet::<ExclusiveFunctionSystem<Marker, F>>::new()
}
}

#[cfg(test)]
mod tests {
use crate::{
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_ecs/src/system/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
resource::Resource,
system::{
DynSystemParam, DynSystemParamState, Local, ParamSet, Query, SystemMeta, SystemParam,
WorldAccessLevel,
},
world::{
FilteredResources, FilteredResourcesBuilder, FilteredResourcesMut,
Expand Down Expand Up @@ -513,6 +514,11 @@ impl<'a> DynParamBuilder<'a> {
/// Creates a new [`DynParamBuilder`] by wrapping a [`SystemParamBuilder`] of any type.
/// The built [`DynSystemParam`] can be downcast to `T`.
pub fn new<T: SystemParam + 'static>(builder: impl SystemParamBuilder<T> + 'a) -> Self {
assert_ne!(
T::world_access_level(),
WorldAccessLevel::Exclusive,
"DynSystemParam cannot hold exclusive system parameters"
);
Self(Box::new(|world, meta| {
DynSystemParamState::new::<T>(builder.build(world, meta))
}))
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
schedule::ScheduleLabel,
system::{
command::HandleError, entity_command::CommandWithEntity, input::SystemInput, Deferred,
IntoObserverSystem, IntoSystem, RegisteredSystem, SystemId,
IntoObserverSystem, IntoSystem, RegisteredSystem, SystemId, WorldAccessLevel,
},
world::{
command_queue::RawCommandQueue, unsafe_world_cell::UnsafeWorldCell, CommandQueue,
Expand Down Expand Up @@ -202,6 +202,10 @@ const _: () = {
entities: f1,
}
}

fn world_access_level() -> WorldAccessLevel {
<(Deferred<CommandQueue>, &Entities) as bevy_ecs::system::SystemParam>::world_access_level()
}
}
// SAFETY: Only reads Entities
unsafe impl<'w, 's> bevy_ecs::system::ReadOnlySystemParam for Commands<'w, 's>
Expand Down
Loading
Loading