logo

Rust crates reviews

Cryptographically verifiable, distributed dependency reviews

crate: legion

https://lib.rs/crates/legion/

Add the last reviewed version to Cargo.toml / [dependencies]:

legion = "0.1.1"

Filter reviews clicking on the numbers in the summary.

Full column names in tooltip hints: rating Negative, rating Neutral, rating Positive, rating Strong, thoroughness, understanding, reviews count.

Neg
Neu
Pos
Str
tho
und
rev
1
1
crate version
rating
date
reviewer
thoroughness, understanding
legion 0.1.1
negative
2019-09-11
medium, low

A low-boilerplate, high performance archetype based ECS.

Pros:

  • Archetypes
  • Low boilerplate
  • MIT Licensed

Cons:

  • Widespread use of 16-bit values is begging for overflows
  • Some O(N) patterns I dislike, fortunately with small C.
  • Not MIRI friendly in even the most trivial of examples.
  • Difficult-to-vet unsafe code, strongly suspect some unsound.
  • Omnipresent low-value logging
  • Tons of dependencies (89)

0.1.1

crev
thoroughnessmedium
understandinglow (thanks to use of unsafe)
ratingnegative
FileRatingNotes
benches/allocation_stress.rs+1No global side effects, no black box use...?
benches/pos_vel.rs+1No global side effects, no black box use...?
examples/hello_world.rs+1
src/borrows.rs+1API lock design concerns me... and I suspect this relies on stable_drop_order to avoid aliasing violations.
src/lib.rs-1Difficult to vet unsafe. Some O(N) and overflow concerns.
src/query.rs-1Difficult to vet unsafe.
src/storage.rs-1Tons of difficult-to-vet UnsafeCell use that leaks some of it's unsafety out to other files.
tests/query_api.rs+1
tests/world_api.rs+1
.cargo_vcs_info.json+1
.cargo-ok+1
.gitignore+1
.travis.yml+1caching cargo might be a bad idea IME
bench.png+1
Cargo.toml+1MIT
Cargo.toml.orig+1MIT
LICENSE+1MIT
readme.md+1
OtherRatingNotes
unsafe-1Lots of hard to reason about unsafe.
miri-1Trivial use chokes up miri.
fs+1
io+1
docs+1
tests+1

src/borrows.rs

LineWhatNotes
17Borrow::aquire_readPossible race condition source. Attempts to increment if >= 0. Theoretically could livelock if sufficiently contested, shouldn't in practice.
33Borrow::aquire_writePossible race condition source. Attempts to go from 0 => -1.
43Drop for Borrow+1
57BorrowedSafe from aliasing violations by virtue of stable_drop_order ? Cannot drop Borrow before value lifetime has ended.
92PartialEq for Borrowed'b lifetime unused...?
98Eq for Borrowed'b lifetime unused...?
128BorrowedMutSafe from aliasing violations by virtue of stable_drop_order ? Cannot drop Borrow before value lifetime has ended.
177BorrowedSliceSafe from aliasing violations by virtue of stable_drop_order ? Cannot drop Borrow before value lifetime has ended.
220BorrowedMutSliceSafe from aliasing violations by virtue of stable_drop_order ? Cannot drop Borrow before value lifetime has ended.
269BorrowedIterSafe from aliasing violations by virtue of stable_drop_order ? Cannot drop Borrow before value lifetime has ended.
EOF

src/lib.rs

LineWhatNotes
1Lib doc comments+1
254WorldIdOnly 16-bit world IDs? I could see this overflowing in practice, especially if using the advertized ability to stream stuff in.
264ArchetypeIdOnly 16-bit chunk IDs? Also, poor alignment.
281EntityStandard dual generation index, I approve... although hot entity IDs could overflow in practice?
310Universe::loggerNot entirely sure I'm a fan of this.
365ComponentIndex & friendsThese Indexes should be used earlier when defining WorldId etc....
409impl EntityBlock+1
431EntityBlock::in_rangeSlightly bogus u32 cast - EntityBlock::new should enforce u32 size if you want a u32 len...
498impl EntityAllocatorFull of O(N/1024) operations that could be O(1). Chunking is fine, but this really should abuse the fact that BLOCK_SIZE is constant more instead of looping.
517EntityAllocator::create_entityA better allocation strategy (IMO) would be to always start with the block we last allocated from. Will have degenerate behavior if we're constantly freeing/allocating from the first block.
625World::merge doc commentConcerning, implies API is unsound
638World::mergeunsafe { ... } - I think this might be sound thanks to &mut self implying we have exclusive access to self.archetypes[?].chunks()[?].entities()
719World::insertunsafe { ... } - I think this might be sound thanks to &mut self implying we have exclusive access to self.archetypes[?].chunks()[?].entities()
720World::insertunsafe { ... } - I think this might be sound thanks to &mut self implying we have exclusive access to self.archetypes[?].chunks()[?].entities()
805World::entity_data_mutunsafe { ... } - I think this might be sound thanks to &mut self implying we have exclusive access to self.archetypes[?].chunks()[?].entities()
841World::prep_archetypeunsafe { ... } - Probably sound - index should be valid - but why not just `.map(
1016EntitySource for IterEntitySourceunsafe { ... } - I think this might be sound thanks to &mut Chunk implying we have exclusive access to chunk.entities()
EOF

src/query.rs

LineWhatNotes
*PhantomDataFrequently used when T is already used in the struct, I'm concerned I'm missing something.
196impl View for (...) validate()unsafe { ... } - 0 <= i < j < types.len(), so both calls to get_unchecked should be sound.
276std::ops::Not for PassthroughOooh, operator overloading abuse. Probably fine?
1065impl Iterator for ZipEntities nextunsafe { ... } - Sketchy, assumes data.len() <= entities.len() and that's not a particularly trivial assertion to prove.
1088ChunkView::entitiesunsafe { ... } - NFI if this is sound or not.
EOF

src/storage.rs

LineWhatNotes
19StorageVecUnsafeCell! Oh no.
39unsafe fn StorageVec::data_mut(&self)Because this doesn't take &mut self, this forces the caller to enforce borrow checking manually.
47ComponentStorage::remove for StorageVecunsafe { ... } - I think this might be sound thanks to &mut self
52ComponentStorage::len for StorageVecunsafe { ... } - Unsound? It's not clear what, if anything, ensures len() isn't being mutated by another borrower.
104unsafe fn Chunk::entities_uncheckedBecause this doesn't take &mut self, this forces the caller to enforce borrow checking manually.
126unsafe fn Chunk::entity_data_unchecked+1?
141unsafe fn Chunk::entity_data_mut_uncheckedDitto.
157Chunk::entity_dataunsafe { ... } - Unsound? "Locks" via borrow types after constructing &T, which is too late.
174Chunk::entity_data_mutunsafe { ... } - Unsound? "Locks" via borrow types after constructing &mut T, which is too late.
199Chunk::shared_dataunsafe { ... } - NFI if this is sound or not. Haven't groked why SharedComponentStore is UnsafeCell or what protects it, if anything.
212Chunk::removeunsafe { ... } - I think this might be sound thanks to &mut self
EOF

Miri Example

use legion::prelude::*;

[test] // PREPEND YOUR OWN POUND SIGN
fn test() {
    let universe = Universe::new(None);
    let mut world = universe.create_world();
    world.insert_from((), vec![(1i32,)]);
}
rustup toolchain install nightly-2019-09-11
rustup component add miri --toolchain=nightly-2019-09-11
cargo +nightly-2019-09-11 miri test
error[E0080]: Miri evaluation error: trying to reborrow for SharedReadWrite, but parent tag <126591> does not have an appropriate item in the borrow stack
    |
    = note: inside call to `<legion::IterEntitySource<std::vec::IntoIter<(i32,)>, (i32,)> as legion::EntitySource>::write` at C:\Users\Mike\.cargo\registry\src\github.com-1ecc6299db9ec823\legion-0.1.1\src\lib.rs:716:29
    = note: inside call to `legion::World::insert::<(), legion::IterEntitySource<std::vec::IntoIter<(i32,)>, (i32,)>>` at C:\Users\Mike\.cargo\registry\src\github.com-1ecc6299db9ec823\legion-0.1.1\src\lib.rs:689:9
note: inside call to `legion::World::insert_from::<(), std::vec::Vec<(i32,)>>` at src\lib.rs:7:5
    --> src\lib.rs:7:5
     |
7    |     world.insert_from((), vec![(1i32,)]);
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside call to `test` at src\lib.rs:4:1
    --> src\lib.rs:4:1
     |
4    | / fn test() {
5    | |     let universe = Universe::new(None);
6    | |     let mut world = universe.create_world();
7    | |     world.insert_from((), vec![(1i32,)]);
8    | | }
     | |_^

TIL

  • TypeId::of::<T>()

© bestia.dev 2023, MIT License, Version: 2023.608.1636

Open source repository for this web app: https://github.com/bestia-dev/cargo_crev_web/