Use a build script to detect if we can use MaybeUninit or NoDrop.
Enabling unstable features automatically is not ideal, but since it's
a soundness issue we should do it.
Use a MaybeUninit-like union on nightly when we can. We use a feature
detection script in build.rs, so that we also go back to the fallback if
the unstable feature changes in an unexpected way.
We need to continue to use NoDrop for best working stable
implementation, but we eagerly use our union solution where we can,
currently only in nightlies.
Rustc feature probe code written by Josh Stone (cuviper),
taken from num-bigint.
Again, stacked borrows model makes the `self.set_len()` call illegal
because we are holding (and are going to use) another raw pointer
derived from self, `tail`.
The benchmark was optimized out totally. We think of that as a good
sign, the new extend became transparent to the compiler and we had to
get smarter in how to fool it.
This simplification -- borrowing self.len instead of self, leads to
an improvement in the extend_from_slice benchmark.
It's also guided by the discussion of stacked borrows; the old code
would be invalid, because the whole self is borrowed while ptr is derived from
self.
This way we cover all users up to 256 at least. The reason these are not
enabled by default is that they slow down the compilation of the crate
by a factor of 2-3x.
In the test, test with Vec first to see how Rust implements panic
recovery while elements drop. If Vec drops all the elements, then we
test that arrayvec does too.
This should perform better in both release and debug mode.
NOTE: This is significant because it changes the drop order of the
elements, and how we handle panicking destructors. If just one of the
destructors panic during ArrayVec drop, clear or truncate, the rest of
the elements should still drop. If we encounter another panic during
that process, however, Rust will abort as usual for panic during
unwinding.