-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SliceIndex impl for pair of Bounds #81108
Conversation
r? @m-ou-se (rust-highfive has picked a reviewer for you, use r? to override) |
16bd67d
to
97c0c24
Compare
97c0c24
to
8ac8935
Compare
let start = match self.0 { | ||
ops::Bound::Unbounded => 0, | ||
ops::Bound::Included(start) => start, | ||
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(), | ||
ops::Bound::Excluded(start) => start + 1, | ||
}; | ||
let end = match self.1 { | ||
ops::Bound::Unbounded => slice.len(), | ||
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(), | ||
ops::Bound::Included(end) => end + 1, | ||
ops::Bound::Excluded(end) => end, | ||
}; | ||
(start..end).index(slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert_len
can make this simpler:
let start = match self.0 { | |
ops::Bound::Unbounded => 0, | |
ops::Bound::Included(start) => start, | |
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(), | |
ops::Bound::Excluded(start) => start + 1, | |
}; | |
let end = match self.1 { | |
ops::Bound::Unbounded => slice.len(), | |
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(), | |
ops::Bound::Included(end) => end + 1, | |
ops::Bound::Excluded(end) => end, | |
}; | |
(start..end).index(slice) | |
unsafe { | |
slice.get_unchecked(self.assert_len(slice.len())) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried looking for a method like this and apparently couldn't find one, huh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry. I only know about it because I implemented it.
let start = match self.0 { | ||
ops::Bound::Unbounded => 0, | ||
ops::Bound::Included(start) => start, | ||
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(), | ||
ops::Bound::Excluded(start) => start + 1, | ||
}; | ||
let end = match self.1 { | ||
ops::Bound::Unbounded => slice.len(), | ||
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(), | ||
ops::Bound::Included(end) => end + 1, | ||
ops::Bound::Excluded(end) => end, | ||
}; | ||
(start..end).index_mut(slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be used here too:
let start = match self.0 { | |
ops::Bound::Unbounded => 0, | |
ops::Bound::Included(start) => start, | |
ops::Bound::Excluded(start) if start == usize::MAX => slice_start_index_overflow_fail(), | |
ops::Bound::Excluded(start) => start + 1, | |
}; | |
let end = match self.1 { | |
ops::Bound::Unbounded => slice.len(), | |
ops::Bound::Included(end) if end == usize::MAX => slice_end_index_overflow_fail(), | |
ops::Bound::Included(end) => end + 1, | |
ops::Bound::Excluded(end) => end, | |
}; | |
(start..end).index_mut(slice) | |
unsafe { | |
slice.get_unchecked_mut(self.assert_len(slice.len())) | |
} |
let start = match self.0 { | ||
ops::Bound::Unbounded => 0, | ||
ops::Bound::Included(start) => start, | ||
ops::Bound::Excluded(start) => start + 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if it is a good idea to implicitly overflow in get_unchecked
(and get_mut
unchecked`). The "unchecked" refers to the slice bounds, how is the caller supposed to know that they also need to guard against overflow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I used the existing code in RangeInclusive
for precedent as that also doesn't guard against overflow. I'm fine just doing a saturated_add instead though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, that's a fair point. But I still feel like this choice (either way) should be documented somewhere.
So, could you give some examples for how you imagine this could be used? The PR has no testcase at all so this is a bit hard to see. |
I just found this PR, which should add the same impls. It has an active FCP, and it has the same question of what its use case would be. |
This effectively allows using the
RangeBounds
trait to index slices, since there aren't any existing ranges that would work otherwise with aBound::Excluded
start. This basically uses the same strategy asRangeInclusive
and just fails if you're trying to do a range starting at exclusiveusize::MAX
, since that effectively would never work.Would require FCP but considering how pairs of bounds are allowed for
RangeBounds
, it seems reasonable to allow them for slices too.(Working on adding tests.)