Skip to content

Commit 3968184

Browse files
authored
Make sure #[track_caller] in EntityCommands::insert_if_neq works as intended (#23986)
intended # Objective Fixes #23962 ## Solution As suggested in the issue: "go back to insert_with_caller so that we can call MaybeLocation::caller() outside of the closure and then pass it through explicitly". ## Testing Added a unit test and made sure it fails without the fix.
1 parent e9e15e5 commit 3968184

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

  • crates/bevy_ecs/src/system/commands

crates/bevy_ecs/src/system/commands/mod.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::{
2727
event::{EntityEvent, Event},
2828
message::Message,
2929
observer::{IntoEntityObserver, IntoObserver},
30+
relationship::RelationshipHookMode,
3031
resource::Resource,
3132
schedule::ScheduleLabel,
3233
system::{
@@ -1485,12 +1486,20 @@ impl<'a> EntityCommands<'a> {
14851486
/// missing.
14861487
#[track_caller]
14871488
pub fn insert_if_neq<T: Component + PartialEq>(&mut self, component: T) -> &mut Self {
1489+
let caller = MaybeLocation::caller();
1490+
14881491
self.queue(move |mut entity: EntityWorldMut| {
14891492
if entity
14901493
.get::<T>()
14911494
.is_none_or(|old_component| *old_component != component)
14921495
{
1493-
entity.insert(component);
1496+
move_as_ptr!(component);
1497+
entity.insert_with_caller(
1498+
component,
1499+
InsertMode::Replace,
1500+
caller,
1501+
RelationshipHookMode::Run,
1502+
);
14941503
}
14951504
})
14961505
}
@@ -2739,6 +2748,47 @@ mod tests {
27392748
assert_eq!(world.get::<P>(entity2).unwrap().0, 42);
27402749
}
27412750

2751+
#[cfg(feature = "track_location")]
2752+
#[test]
2753+
fn insert_component_if_not_equal_tracks_caller() {
2754+
use core::panic::Location;
2755+
2756+
#[derive(Component, PartialEq)]
2757+
struct P(u8);
2758+
2759+
let mut world = World::default();
2760+
let mut command_queue = CommandQueue::default();
2761+
2762+
let entity = Commands::new(&mut command_queue, &world)
2763+
.spawn(P(41u8))
2764+
.id();
2765+
command_queue.apply(&mut world);
2766+
world.clear_trackers();
2767+
2768+
macro_rules! insert_if_neq_with_expected_caller {
2769+
($commands:expr, $entity:expr, $component:expr) => {{
2770+
$commands.entity($entity).insert_if_neq($component);
2771+
Location::caller()
2772+
}};
2773+
}
2774+
2775+
let expected = insert_if_neq_with_expected_caller!(
2776+
Commands::new(&mut command_queue, &world),
2777+
entity,
2778+
P(42u8)
2779+
);
2780+
command_queue.apply(&mut world);
2781+
2782+
assert_eq!(
2783+
world
2784+
.entity(entity)
2785+
.get_changed_by::<P>()
2786+
.unwrap()
2787+
.into_option(),
2788+
Some(expected)
2789+
);
2790+
}
2791+
27422792
#[test]
27432793
fn remove_components() {
27442794
let mut world = World::default();

0 commit comments

Comments
 (0)