From: Ralf Jung Date: Sat, 28 Jul 2018 11:55:17 +0000 (+0200) Subject: simplify len macro: No longer require the type X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=b0a82d9314083cad0c985c8f5f752749c9ae96ca;p=rust.git simplify len macro: No longer require the type Also use ident, not expr, to avoid accidental side-effects --- diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0b62fdce7f3..a807e92a2a8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2337,18 +2337,25 @@ fn into_iter(self) -> IterMut<'a, T> { } } +// Macro helper functions +#[inline(always)] +fn size_from_ptr(_: *const T) -> usize { + mem::size_of::() +} + // Inlining is_empty and len makes a huge performance difference macro_rules! is_empty { // The way we encode the length of a ZST iterator, this works both for ZST // and non-ZST. - ($self: expr) => {$self.ptr == $self.end} + ($self: ident) => {$self.ptr == $self.end} } macro_rules! len { - ($T: ty, $self: expr) => {{ - if mem::size_of::<$T>() == 0 { - ($self.end as usize).wrapping_sub($self.ptr as usize) + ($self: ident) => {{ + let start = $self.ptr; + if size_from_ptr(start) == 0 { + ($self.end as usize).wrapping_sub(start as usize) } else { - $self.end.offset_from($self.ptr) as usize + $self.end.offset_from(start) as usize } }} } @@ -2360,7 +2367,7 @@ impl<'a, T> $name<'a, T> { // Helper function for creating a slice from the iterator. #[inline(always)] fn make_slice(&self) -> &'a [T] { - unsafe { from_raw_parts(self.ptr, len!(T, self)) } + unsafe { from_raw_parts(self.ptr, len!(self)) } } // Helper function for moving the start of the iterator forwards by `offset` elements, @@ -2398,7 +2405,7 @@ unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T { impl<'a, T> ExactSizeIterator for $name<'a, T> { #[inline(always)] fn len(&self) -> usize { - unsafe { len!(T, self) } + unsafe { len!(self) } } #[inline(always)] @@ -2429,7 +2436,7 @@ fn next(&mut self) -> Option<$elem> { #[inline] fn size_hint(&self) -> (usize, Option) { - let exact = unsafe { len!(T, self) }; + let exact = unsafe { len!(self) }; (exact, Some(exact)) } @@ -2440,7 +2447,7 @@ fn count(self) -> usize { #[inline] fn nth(&mut self, n: usize) -> Option<$elem> { - if n >= unsafe { len!(T, self) } { + if n >= unsafe { len!(self) } { // This iterator is now empty. if mem::size_of::() == 0 { // We have to do it this way as `ptr` may never be 0, but `end` @@ -2471,7 +2478,7 @@ fn try_fold(&mut self, init: B, mut f: F) -> R where // manual unrolling is needed when there are conditional exits from the loop let mut accum = init; unsafe { - while len!(T, self) >= 4 { + while len!(self) >= 4 { accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?; @@ -2562,7 +2569,7 @@ fn try_rfold(&mut self, init: B, mut f: F) -> R where // manual unrolling is needed when there are conditional exits from the loop let mut accum = init; unsafe { - while len!(T, self) >= 4 { + while len!(self) >= 4 { accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?; @@ -2769,7 +2776,7 @@ impl<'a, T> IterMut<'a, T> { /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn into_slice(self) -> &'a mut [T] { - unsafe { from_raw_parts_mut(self.ptr, len!(T, self)) } + unsafe { from_raw_parts_mut(self.ptr, len!(self)) } } }