-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 panic-safe slicing methods #1325
Conversation
07936d3
to
5b0e31a
Compare
5b0e31a
to
be5eb6f
Compare
Is there any reason the originals need panics? Isn't it reasonable to just return an empty slice? Other languages do that. Also, failing when the edges aren't perfect seems silly. I know &[..90] // [1, 2, 3, 4, 5]
&[90..1] // []
&[90..104] // [] |
Could the existing |
@mdinger triggering this behaviour hints at a logic error. Do we have any other cases where the standard library "squashes" inputs in a best-effort way? (nothing off the top of my head) |
I suppose but it also isn't a strong guarantee at all. These 2 are just as incorrect but only one of each errors: // Both just as wrong when you want the entire slice but go one too low
&[1..]
&[-1..]
// Both just as wrong when you want up to the last element
&[..len-1]
&[..len+1] From collections, this isn't an error but returns use std::collections::BTreeMap;
let mut map = BTreeMap::new();
map.insert("foo", 89);
println!("{:?}", map.get("charles")); So, likewise it'd make sense for a disjoint slice to return a I just can't see how |
If the slicing operator is supposed to preserve the length of the input in the output, that is |
To add to the subjectivity of what is weird or isn't: I would found it surprising if |
Okay, then if preserving the size is part of correct slice behaviour then the current behaviour should be fine (I don't have any exact use case anyway) but if the reason for the panics is to strictly to prevent off the end memory access, that seems silly; they should return whatever the valid intersection happens to be. It's too bad normal slicing can't return option (too unergonomic I guess). This RFC seems like a good idea. |
This is kind've a fundamental philosophical difference. Some have argued that indexing should behave optimistically and do "modulo len", but I think that's definitely step too far (also incoherent on empty slices). Being strict on all indexing seems consistent to me. Of course we can't magically detect semantic errors like E: within limits. A check must be made, but making extra checks to be "extra helpful" is a harder pill to swallow. |
Okay. I didn't know it had previously been discussed and it looked kinda like something which had just slipped through unnoticed. Strictness does fit the Rust theme so it isn't too unusual I guess. |
I dunno. For normal indexing where you need to return an |
For all my code, the indices are derived from properties of the to-be-sliced value, so if they're ever messed up it means my code is wrong, and I'd like to know ASAP. |
Well, indexing returning option would easily handle the out of bounds case (unless it was |
assert_eq!(a.get_range(..3), Some(&a[..3])); | ||
assert_eq!(a.get_range(2..5), Some(&a[2..5])); | ||
assert_eq!(a.get_range(..6), None); | ||
assert_eq!(a.get_range(4..2), None); |
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.
An alternative would be:
assert_eq!(a.get_range(1..), &a[1..]);
assert_eq!(a.get_range(..3), &a[..3]);
assert_eq!(a.get_range(2..5), &a[2..5]);
assert_eq!(a.get_range(..6), &[]);
assert_eq!(a.get_range(4..2), &[]);
For what it’s worth, out of bounds slices are clamped when indexing in Python: >>> [1, 2, 3][:2]
[1, 2]
>>> [1, 2, 3][:10]
[1, 2, 3] |
Other data point, from Java, which in some ways its strictness is similar If start or end are out of bounds, IndexOutOfBoundsException is thrown. On Wed, Oct 21, 2015, 1:12 AM Simon Sapin notifications@github.com wrote:
|
Fuzzy slice boundaries are even more strange if you apply the thought experiment to I totally support the idea behind the RFC, nonpanicking slicing would be great. Implementation though, I think a trait named for Index would be better.
|
👍 We had to implement this in the Redox kernel to avoid kernel panics. We see no reason for this method not existing in libcore. |
I also had to deal with this when writing kernel code. 👍 |
Could't we just make |
@Kimundi breaking change, I think? |
@nagisa: Not really, if the generic method still accepts the current |
Doing as @Kimundi proposes would of course necessitate making There are two problems with this:
I definitely think it'd be reasonable to have a solution here, I'm just wondering if we're lacking the tooling today to make the solution we'd want longterm, at the moment. |
Instead of having |
Yeah, just making them generic methods is what I had in mind. |
ring also had to implement this: https://github.com/briansmith/ring/blob/00830b53fd1c93e20bdba1f6e130ad8816b25a17/src/input.rs#L275 |
Seems like a useful addition; reusing |
@barosl would you be interested in updating this RFC to recommend reusing the existing |
Yeppeun version