diff options
| author | bors <bors@rust-lang.org> | 2021-05-27 13:05:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-05-27 13:05:57 +0000 |
| commit | ea78d1edf364dd3a4b5ff430f76e2bdd3a713a45 (patch) | |
| tree | 833d19a86e0ddd53516c2907505bd37876afdabe /library/alloc/src/vec | |
| parent | 8d1e3d3b74fa80ce14af6ec143f061897684582b (diff) | |
| parent | 04d34a97d1d47676331479e24e5afaf2583cb8e5 (diff) | |
| download | rust-ea78d1edf364dd3a4b5ff430f76e2bdd3a713a45.tar.gz rust-ea78d1edf364dd3a4b5ff430f76e2bdd3a713a45.zip | |
Auto merge of #85737 - scottmcm:vec-calloc-option-nonzero, r=m-ou-se
Enable Vec's calloc optimization for Option<NonZero> Someone on discord noticed that `vec![None::<NonZeroU32>; N]` wasn't getting the optimization, so here's a PR 🙃 We can certainly do this in the standard library because we know for sure this is ok, but I think it's also a necessary consequence of documented guarantees like those in https://doc.rust-lang.org/std/option/#representation and https://doc.rust-lang.org/core/num/struct.NonZeroU32.html It feels weird to do this without adding a test, but I wasn't sure where that would belong. Is it worth adding codegen tests for these?
Diffstat (limited to 'library/alloc/src/vec')
| -rw-r--r-- | library/alloc/src/vec/is_zero.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index b5739970b6e..6fade636df9 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -69,3 +69,36 @@ unsafe impl<T: ?Sized> IsZero for Option<Box<T>> { self.is_none() } } + +// `Option<num::NonZeroU32>` and similar have a representation guarantee that +// they're the same size as the corresponding `u32` type, as well as a guarantee +// that transmuting between `NonZeroU32` and `Option<num::NonZeroU32>` works. +// While the documentation officially makes in UB to transmute from `None`, +// we're the standard library so we can make extra inferences, and we know that +// the only niche available to represent `None` is the one that's all zeros. + +macro_rules! impl_is_zero_option_of_nonzero { + ($($t:ident,)+) => {$( + unsafe impl IsZero for Option<core::num::$t> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } + } + )+}; +} + +impl_is_zero_option_of_nonzero!( + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroUsize, + NonZeroIsize, +); |
