arraytools
arraytools copied to clipboard
add support for const generics through feature
Motiviation
In some code I'm working on, being able to use map on arrays with lengths specified through const generics would be a great thing to have. However, this code only works for arrays of a few specified lengths. I could publish a new crate supporting this, but most of the functionality is already included in this crate. So I decided to modify it.
Problems
- Push and Pop cannot work using const generics, because currently Rust does not support doing math with const generic.
- To and From tuple cannot work using const generics, their type is generated using macros
- In some cases, FnOnce is taken in without const generics. This distinction is really hard to make currently because you cannot put bounds on const generics. Specialization would also fix this.
- In some cases (like with repeat), the last element is not cloned but moved. This cannot work with const generics without specializations or bounds (same as previous point)
- (some) Unsafe code is required (!)
Solutions
The implementation proposed in this pull request makes some compromises to still make everything work
- The implementation using const generic is feature-gated.
- push and pop are only implemented when the length is known and smaller than 32. This is still done with macros. This way push and pop won't work with truly const generic arrays, but they will work in situations where they previously worked.
- The same is done with to and from tuple
- In the const generic version, FnMut is always taken, as it imposes as few restrictions as possible, though this is obviously not ideal.
- All elements are cloned. The last element is not moved. I made this change as well for the regular non-const generic version as I think this feature doesn't add much. I clone more or less does not make much of a difference. In fact, rust might still be able to optimize this away. If this is not what you like however, the cloning/moving could be feature gated behind the const-generics feature. I chose not to do this so all tests are the same between the two implementations and the implementations are more consistent. Our opinions may differ on this one
- The unsafe code required is just an optimization, to avoid needing to initialize arrays twice. To avoid this, MaybeUninit can be used. MaybeUninit can be guaranteed to be safe. To avoid needing to prove this ourselves, I added the
array_init
dependency which does this for us. This dependency is gated behind the const-generics feature.
All tests pass on both versions of arraytools. Please let me know what you think of this!
Checks in the CI fail because all features are enabled in the CI, even on rust targets which do not yet support const generics. Disabling the const-generics
feature for these targets should fix the CI