Repository navigation
Add BundleRemover - #18521
Add BundleRemover#18521
BundleRemover#18521Conversation
| Option<&mut Table>, | ||
| &Components, | ||
| &[ComponentId], | ||
| ) -> (bool, T), |
There was a problem hiding this comment.
The old code intentionally used a const generic instead of an ordinary bool to make sure that the branches optimized away. Do we need to preserve that?
Even if we don't, it looks like there are only two functions passed as pre_remove, and one has hard-coded true and the other hard-coded false. It might be simpler to make a separate drop: bool parameter to avoid the tuple and make it clear that it doesn't depend on the values passed to pre_remove.
There was a problem hiding this comment.
The old code intentionally used a const generic instead of an ordinary
boolto make sure that the branches optimized away. Do we need to preserve that?
It's an impl Fn, and with only two closures types, monomorphization will effectively the same thing. They are both generic, and both bools are constants.
It might be simpler to make a separate
drop: boolparameter to avoid the tuple and make it clear that it doesn't depend on the values passed topre_remove.
I mean, we could add that restriction, but I don't see the point. Letting it depend on it seems more flexible for the future.
| &mut deferred_world, | ||
| old_archetype, | ||
| let mut remover = BundleRemover::new::<T>(self.world, self.location.archetype_id, true)?; | ||
| // SAFETY: The passed location has the sane archetype as the remover, since they came from the same location. |
There was a problem hiding this comment.
Would it make sense to pass the full EntityLocation to BundleRemover::new instead of just ArchetypeId? That would let you get rid of the safety requirement here.
And do you also need to require that this is the right EntityLocation for the given Entity? Or would that just be a logic bug and not a soundness bug?
There was a problem hiding this comment.
Would it make sense to pass the full
EntityLocationtoBundleRemover::newinstead of justArchetypeId? That would let you get rid of the safety requirement here.
We could but then the remover would be entity specific instead of archetype specific IIUC. So I'd rather leave it as is.
And do you also need to require that this is the right
EntityLocationfor the givenEntity? Or would that just be a logic bug and not a soundness bug?
Only the archetypes need to match for now I think. In principal, we could make remove take just a table row and store the archetype id and row and table id on the remover. But this was just easier IMO. I'm open to changing that though!
| pub(crate) struct BundleRemover<'w> { | ||
| world: UnsafeWorldCell<'w>, | ||
| bundle_info: ConstNonNull<BundleInfo>, | ||
| old_and_new_table: Option<(NonNull<Table>, NonNull<Table>)>, |
There was a problem hiding this comment.
Is it worth trying to make this look more like BundleInserter? That records the current table and archetype pointers along with an enum ArchetypeMoveType that has the new ones.
Although I suppose one major difference is that you don't need to do anything on a remove that doesn't change archetypes, while an insert might be changing the values.
There was a problem hiding this comment.
It's been a while since I wrote this, so I don't remember the details. But IIRC, I originally tried to do this with effectively the same structure as BundleInserter and ended up running into issues. I think it was easier to justify safety where accessing the new table mutably could be the same as the old table's mutable pointer. I could take another stab at it, but I don't feel it would be worth it.
There was a problem hiding this comment.
Yeah, I agree it's not worth revisiting. I was just surprised that it looked so different! But if you already tried it that way then there must be a good reason for the differences!
| } | ||
| } | ||
|
|
||
| // SAFETY: We have exclusive world access so our pointers can't be invalidated externally |
There was a problem hiding this comment.
This safety comment is on a struct rather than an unsafe block, so I don't think it will get seen. Did you mean to put it somewhere else, or to put it as a doc comment for the struct?
There was a problem hiding this comment.
This was just copied from BundleInserter. I don't mind it, but I can understand your point. I wouldn't be opposed to moving it for all Bundle*er maybe in a different pr.
There was a problem hiding this comment.
Ah, okay, I didn't realize this was an existing pattern. That makes sense, then!
| require_all: bool, | ||
| ) -> Option<Self> { | ||
| let bundle_info = world.bundles.get_unchecked(bundle_id); | ||
| // SAFETY: Ensured by caller and that intersections are never `None`. |
There was a problem hiding this comment.
I don't understand this safety comment. What does "and that intersections are never None" refer to?
The safety requirements for remove_bundle_from_archetype are "archetype_id must exist and components in bundle_info must exist". The caller is ensuring that archetype_id exists/is valid. Does the fact that you have a BundleId prove that the components all exist?
There was a problem hiding this comment.
Yeah, my comment was poorly written. And yeah, you can't make a bundle without having component ids, so we should be good there.
|
I don't know if it's policy or just a pattern I've noticed, but since there's two approvals (thanks!), I'll mark ready for final. Let me know if there's some step I'm missing. |
Yup, that's the policy! See https://bevyengine.org/learn/contribute/helping-out/reviewing-pull-requests/#how-pull-requests-are-merged:
(Sorry, I probably should have changed the tag when I approved!) |
|
You're good! I thought I read that somewhere... |
# Objective It has long been a todo item in the ecs to create a `BundleRemover` alongside the inserter, spawner, etc. This is an uncontroversial first step of bevyengine#18514. ## Solution Move existing code from complex helper functions to one generalized `BundleRemover`. ## Testing Existing tests.
Objective
It has long been a todo item in the ecs to create a
BundleRemoveralongside the inserter, spawner, etc.This is an uncontroversial first step of #18514.
Solution
Move existing code from complex helper functions to one generalized
BundleRemover.Testing
Existing tests.