Skip to content

Commit ef94b29

Browse files
committed
Merge branch 'string-get-slice' of https://github.com/sfackler/rfcs
2 parents 8f5c1cd + 293adaf commit ef94b29

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

text/0000-panic-safe-slicing.md

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
- Feature Name: panic_safe_slicing
2+
- Start Date: 2015-10-16
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
8+
Add "panic-safe" or "total" alternatives to the existing panicking indexing syntax.
9+
10+
# Motivation
11+
12+
`SliceExt::get` and `SliceExt::get_mut` can be thought as non-panicking versions of the simple
13+
indexing syntax, `a[idx]`, and `SliceExt::get_unchecked` and `SliceExt::get_unchecked_mut` can
14+
be thought of as unsafe versions with bounds checks elided. However, there is no such equivalent for
15+
`a[start..end]`, `a[start..]`, or `a[..end]`. This RFC proposes such methods to fill the gap.
16+
17+
# Detailed design
18+
19+
The `get`, `get_mut`, `get_unchecked`, and `get_unchecked_mut` will be made generic over `usize`
20+
as well as ranges of `usize` like slice's `Index` implementation currently is. This will allow e.g.
21+
`a.get(start..end)` which will behave analagously to `a[start..end]`.
22+
23+
Because methods cannot be overloaded in an ad-hoc manner in the same way that traits may be
24+
implemented, we introduce a `SliceIndex` trait which is implemented by types which can index into a
25+
slice:
26+
```rust
27+
pub trait SliceIndex<T> {
28+
type Output: ?Sized;
29+
30+
fn get(self, slice: &[T]) -> Option<&Self::Output>;
31+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output>;
32+
unsafe fn get_unchecked(self, slice: &[T]) -> &Self::Output;
33+
unsafe fn get_mut_unchecked(self, slice: &[T]) -> &mut Self::Output;
34+
fn index(self, slice: &[T]) -> &Self::Output;
35+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
36+
}
37+
38+
impl<T> SliceIndex<T> for usize {
39+
type Output = T;
40+
// ...
41+
}
42+
43+
impl<T, R> SliceIndex<T> for R
44+
where R: RangeArgument<usize>
45+
{
46+
type Output = [T];
47+
// ...
48+
}
49+
```
50+
51+
And then alter the `Index`, `IndexMut`, `get`, `get_mut`, `get_unchecked`, and `get_mut_unchecked`
52+
implementations to be generic over `SliceIndex`:
53+
```rust
54+
impl<T> [T] {
55+
pub fn get<I>(&self, idx: I) -> Option<I::Output>
56+
where I: SliceIndex<T>
57+
{
58+
idx.get(self)
59+
}
60+
61+
pub fn get_mut<I>(&mut self, idx: I) -> Option<I::Output>
62+
where I: SliceIndex<T>
63+
{
64+
idx.get_mut(self)
65+
}
66+
67+
pub unsafe fn get_unchecked<I>(&self, idx: I) -> I::Output
68+
where I: SliceIndex<T>
69+
{
70+
idx.get_unchecked(self)
71+
}
72+
73+
pub unsafe fn get_mut_unchecked<I>(&mut self, idx: I) -> I::Output
74+
where I: SliceIndex<T>
75+
{
76+
idx.get_mut_unchecked(self)
77+
}
78+
}
79+
80+
impl<T, I> Index<I> for [T]
81+
where I: SliceIndex<T>
82+
{
83+
type Output = I::Output;
84+
85+
fn index(&self, idx: I) -> &I::Output {
86+
idx.index(self)
87+
}
88+
}
89+
90+
impl<T, I> IndexMut<I> for [T]
91+
where I: SliceIndex<T>
92+
{
93+
fn index_mut(&self, idx: I) -> &mut I::Output {
94+
idx.index_mut(self)
95+
}
96+
}
97+
```
98+
99+
# Drawbacks
100+
101+
- The `SliceIndex` trait is unfortunate - it's tuned for exactly the set of methods it's used by.
102+
It only exists because inherent methods cannot be overloaded the same way that trait
103+
implementations can be. It would most likely remain unstable indefinitely.
104+
- Documentation may suffer. Rustdoc output currently explicitly shows each of the ways you can
105+
index a slice, while there will simply be a single generic implementation with this change. This
106+
may not be that bad, though. The doc block currently seems to provided the most valuable
107+
information to newcomers rather than the trait bound, and that will still be present with this
108+
change.
109+
110+
# Alternatives
111+
112+
- Stay as is.
113+
- A previous version of this RFC introduced new `get_slice` etc methods rather than overloading
114+
`get` etc. This avoids the utility trait but is somewhat less ergonomic.
115+
- Instead of one trait amalgamating all of the required methods, we could have one trait per
116+
method. This would open a more reasonable door to stabilizing those traits, but adds quite a lot
117+
more surface area. Replacing an unstable `SliceIndex` trait with a collection would be
118+
backwards compatible.
119+
120+
# Unresolved questions
121+
122+
None

0 commit comments

Comments
 (0)