Skip to content

Commit cb7810b

Browse files
committed
Added detail about mut, ... for matching, and future-proofing
1 parent f75f602 commit cb7810b

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

active/0000-slice-notation.md

+50
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ Like `Index`, uses of this notation will auto-deref just as if they were method
8585
invocations. So if `T` implements `Slice<uint, [U]>`, and `s: Smaht<T>`, then
8686
`s[]` compiles and has type `&[U]`.
8787

88+
Note that slicing is "exclusive" (so `[n..m]` is the interval `n <= x
89+
< m`), while `..` in `match` patterns is "inclusive". To avoid
90+
confusion, we propose to change the `match` notation to `...` to
91+
reflect the distinction. The reason to change the notation, rather
92+
than the interpretation, is that the exclusive (respectively
93+
inclusive) interpretation is the right default for slicing
94+
(respectively matching).
95+
8896
## Rationale for the notation
8997

9098
The choice of square brackets for slicing is straightforward: it matches our
@@ -98,12 +106,54 @@ for slicing has precedent in Perl and D.
98106
See [Wikipedia](http://en.wikipedia.org/wiki/Array_slicing) for more on the
99107
history of slice notation in programming languages.
100108

109+
### The `mut` qualifier
110+
111+
It may be surprising that `mut` is used as a qualifier in the proposed
112+
slice notation, but not for the indexing notation. The reason is that
113+
indexing includes an implicit dereference. If `v: Vec<Foo>` then
114+
`v[n]` has type `Foo`, not `&Foo` or `&mut Foo`. So if you want to get
115+
a mutable reference via indexing, you write `&mut v[n]`. More
116+
generally, this allows us to do resolution/typechecking prior to
117+
resolving the mutability.
118+
119+
This treatment of `Index` matches the C tradition, and allows us to
120+
write things like `v[0] = foo` instead of `*v[0] = foo`.
121+
122+
On the other hand, this approach is problematic for slicing, since in
123+
general it would yield an unsized type (under DST) -- and of course,
124+
slicing is meant to give you a fat pointer indicating the size of the
125+
slice, which we don't want to immediately deref. But the consequence
126+
is that we need to know the mutability of the slice up front, when we
127+
take it, since it determines the type of the expression.
128+
101129
# Drawbacks
102130

103131
The main drawback is the increase in complexity of the language syntax. This
104132
seems minor, especially since the notation here is essentially "finishing" what
105133
was started with the `Index` trait.
106134

135+
## Limitations in the design
136+
137+
Like the `Index` trait, this forces the result to be a reference via
138+
`&`, which may rule out some generalizations of slicing.
139+
140+
One way of solving this problem is for the slice methods to take
141+
`self` (by value) rather than `&self`, and in turn to implement the
142+
trait on `&T` rather than `T`. Whether this approach is viable in the
143+
long run will depend on the final rules for method resolution and
144+
auto-ref.
145+
146+
In general, the trait system works best when traits can be applied to
147+
types `T` rather than borrowed types `&T`. Ultimately, if Rust gains
148+
higher-kinded types (HKT), we could change the slice type `S` in the
149+
trait to be higher-kinded, so that it is a *family* of types indexed
150+
by lifetime. Then we could replace the `&'a S` in the return value
151+
with `S<'a>`. It should be possible to transition from the current
152+
`Index` and `Slice` trait designs to an HKT version in the future
153+
without breaking backwards compatibility by using blanket
154+
implementations of the new traits (say, `IndexHKT`) for types that
155+
implement the old ones.
156+
107157
# Alternatives
108158

109159
For improving the ergonomics of `as_slice`, there are two main alternatives.

0 commit comments

Comments
 (0)