-
Notifications
You must be signed in to change notification settings - Fork 57
Description
There's a lot of code similar to this, on ArrayVec:
fn deref(&self) -> &Self::Target {
&self.data.as_slice()[..self.len as usize]
}We invoke something like this every single time we try to get a slice, directly or indirectly (such as via .iter()).
In world of unsafe implementations, one would normally maintain the invariant that len <= self.data.len() and unsafely create the slice. This is against what tinyvec tries to achieve. Sadly, the trade-off is that this will basically always insert panic into the generated code.
In practice, this panic can only happen if there's a bug in ArrayVec (forgetting to update len properly, missed assumption) or user does something sketchy like unsafely modify the field.
There is a different option however: change the function to look more like
fn deref(&self) -> &Self::Target {
let len = self.len as usize;
let s = &self.data.as_slice();
if len < s.len() {
&s[..len]
} else {
s
}
}This (presumably) compiles to code that doesn't have a panic and it behaves the same as usual in non-weird code. The only change in behaviour is that instead of crashing on ArrayVec bug or due to some unsafe user code (when self.len grows past capacity), it'll now give the full capacity. For all currently-working code it stays working, but probably faster (not slower, for sure...). Any currently-broken code is presumably already crashing, if such code even exists.
We can recover slight bit of previous behaviour with debug asserts I suppose...