#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
- /// Whether this value is zero
+ /// Whether this value's representation is all zeros
fn is_zero(&self) -> bool;
}
}
}
+unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
+ #[inline]
+ fn is_zero(&self) -> bool {
+ // Because this is generated as a runtime check, it's not obvious that
+ // it's worth doing if the array is really long. The threshold here
+ // is largely arbitrary, but was picked because as of 2022-05-01 LLVM
+ // can const-fold the check in `vec![[0; 32]; n]` but not in
+ // `vec![[0; 64]; n]`: https://godbolt.org/z/WTzjzfs5b
+ // Feel free to tweak if you have better evidence.
+
+ N <= 32 && self.iter().all(IsZero::is_zero)
+ }
+}
+
// `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
// For fat pointers, the bytes that would be the pointer metadata in the `Some`
// variant are padding in the `None` variant, so ignoring them and