Skip to content

Commit

Permalink
Rollup merge of rust-lang#127748 - scottmcm:option_len, r=joboet
Browse files Browse the repository at this point in the history
Use Option's discriminant as its size hint

I was looking at this in MIR after a question on discord, and noticed that it ends up with a switch in MIR (<https://rust.godbolt.org/z/3q4cYnnb3>), which it doesn't need because (as `Option::as_slice` uses) the discriminant is already the length.
  • Loading branch information
matthiaskrgr authored Jul 18, 2024
2 parents b0c85ba + ad3db57 commit d1d9893
Showing 1 changed file with 17 additions and 7 deletions.
24 changes: 17 additions & 7 deletions core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,13 @@ impl<T> Option<T> {
}
}

#[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.
Expand Down Expand Up @@ -812,7 +819,7 @@ impl<T> Option<T> {
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(),
)
}
}
Expand Down Expand Up @@ -869,7 +876,7 @@ impl<T> Option<T> {
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(),
)
}
}
Expand Down Expand Up @@ -2242,10 +2249,8 @@ impl<A> Iterator for Item<A> {

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.opt {
Some(_) => (1, Some(1)),
None => (0, Some(0)),
}
let len = self.len();
(len, Some(len))
}
}

Expand All @@ -2256,7 +2261,12 @@ impl<A> DoubleEndedIterator for Item<A> {
}
}

impl<A> ExactSizeIterator for Item<A> {}
impl<A> ExactSizeIterator for Item<A> {
#[inline]
fn len(&self) -> usize {
self.opt.len()
}
}
impl<A> FusedIterator for Item<A> {}
unsafe impl<A> TrustedLen for Item<A> {}

Expand Down

0 comments on commit d1d9893

Please sign in to comment.