Repository navigation
Conversation
BREAKING CHANGE: ComponentId no longer requires Send + Sync; World/WorldRef are !Send, Query is Send/Sync only when its tuple is, par_* systems bound their tuples, thread-bound components panic on off-thread access. App::run no longer steals a world refcount (use-after-free); frame_action/run_action added, app runs serialized.
WorldRef: Deref<Target=World> transmutes &WorldRef -> &World, sound only if both share layout. World was repr(Rust) while WorldRef was repr(C), so field order was not guaranteed. Mark World repr(C) and add a const size/align assertion at the transmute so any future layout drift fails to compile.
The IMPLS_SEND/IMPLS_SYNC probe (ImplementsSend::<T>::IMPLS) relies on the blanket DoesNotImpl fallback for types that are not Send/Sync, but that trait was not in scope in the component-trait macros. Any !Send/!Sync binding-type component therefore failed to compile, which had been masked by giving Rest bogus `unsafe impl Send/Sync` over its raw pointers (a live server handle). Bring DoesNotImpl into scope inside each IMPLS_SEND/IMPLS_SYNC const block so the probe resolves to false instead of erroring, and drop Rest's fake impls so it is honestly !Send/!Sync and guarded by the world's thread-affinity checks.
cast_mut returned &'a mut dyn Trait from a safe fn taking a Copy EntityView, with the lifetime tied to the world borrow rather than a unique borrow. Two calls for the same entity+id minted aliasing &mut in safe code (UB). Mark it unsafe and document the no-aliasing precondition. cast (shared) stays safe since a &mut can no longer be created without unsafe.
The callback trampolines use extern "C-unwind" so a panic in a user system/observer/hook unwinds back to the Rust caller (e.g. the app loop's catch_unwind). That unwind passes through flecs C frames, which is only defined if the C carries unwind info. flecs.c was compiled without it, making the unwind UB on targets that omit unwind tables by default. Add -fexceptions and -fasynchronous-unwind-tables on non-wasm (ignored where unsupported).
…ed entities/get_mut, range offset, gated multi_src_get, unlock on panic)
… dense field_at, borrow-tied field lifetimes, null guards, and public try_field/FieldError
…e, drop dead fields_tuple
…strings, run_each_iter consistency, Display impls, unwind tables)
…and table locks, docs for is_valid/has_enum/child
…gn and set_ptr checks, try_assign API, IntoEntity widening
… handle, correct world op docs
…server null derefs, non-static term names, Debug impls, try_term_at_type)
…omponent array growth to index, abort on lifecycle hook panics
…read-local, drop double ecs_opaque_init, null-check enum constant ensure
…nd Debug/Eq for system/observer/alert
…tead of silent drops and panics
…inter layout assert, fix ecs_get_ptr_t Default recursion
…ros, add try_first_id/try_second_id, document core/world modules, re-export assert_is_type
… compiles without default features
…ts for unsafe blocks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changelog
Worldis now!Send/!Sync(one world per thread). In exchange, components no longer need to beSend— you can now storeRc, raw pointers, etc.QueryisSend/Synconly when its component types are.safety-locksfeature:get::<(&mut Pos, &Pos)>()now panics (same entity, always aliases).on_replacehooks only fire when the component already existed (previs always a valid value). First-time sets (including everything inside one deferred batch) no longer invoke the hook.cast/cast_mut(query traits) andTable::neware nowunsafe fn.Iter::field/field_mutresults can no longer outlive the iterator borrow.Send.World::components_array/components_mapare no longer public.Send/SyncfromOpaque,EcsIdentifier,EcsPoly, andEntityView<'static>. Raw*mut ecs_world_tno longer converts toWorldRefin safe code — useunsafe WorldRef::from_ptr.✨ Added
try_field(+FieldError),try_build,try_assign*,try_first_id/try_second_id, andtry_term_at_type.AppandAsyncStageowning handles,world.stage(), andmerge().HashforEntityView/IdView;Debug/Eq/Displayfor systems, observers, and alerts;ClonedTuplere-export.set_first/assign_*now acceptimpl IntoEntity(more types work, existing code is unaffected).🐛 Fixed