From ad3db57a52986ebafc06ee37a2e23ce21e463fb6 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 14 Jul 2024 22:02:13 -0700 Subject: [PATCH] Use Option's discriminant as its size hint --- core/src/option.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/core/src/option.rs b/core/src/option.rs index 8ec7716012f59..1a8fe1e6051ad 100644 --- a/core/src/option.rs +++ b/core/src/option.rs @@ -770,6 +770,13 @@ impl Option { } } + #[inline] + const fn len(&self) -> usize { + // Using the intrinsic avoids emitting a branch to get the 0 or 1. + let discriminant: isize = crate::intrinsics::discriminant_value(self); + discriminant as usize + } + /// Returns a slice of the contained value, if any. If this is `None`, an /// empty slice is returned. This can be useful to have a single type of /// iterator over an `Option` or slice. @@ -812,7 +819,7 @@ impl Option { unsafe { slice::from_raw_parts( (self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), - self.is_some() as usize, + self.len(), ) } } @@ -869,7 +876,7 @@ impl Option { unsafe { slice::from_raw_parts_mut( (self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), - self.is_some() as usize, + self.len(), ) } } @@ -2242,10 +2249,8 @@ impl Iterator for Item { #[inline] fn size_hint(&self) -> (usize, Option) { - match self.opt { - Some(_) => (1, Some(1)), - None => (0, Some(0)), - } + let len = self.len(); + (len, Some(len)) } } @@ -2256,7 +2261,12 @@ impl DoubleEndedIterator for Item { } } -impl ExactSizeIterator for Item {} +impl ExactSizeIterator for Item { + #[inline] + fn len(&self) -> usize { + self.opt.len() + } +} impl FusedIterator for Item {} unsafe impl TrustedLen for Item {}