RFC 0495: array-pattern-changes

lang (typesystem | slice | patterns | array | machine)

Summary

Change array/slice patterns in the following ways:

Motivation

Before DST (and after the removal of ~[T]), there were only two types based on [T]: &[T] and &mut [T]. With DST, we can have many more types based on [T], Box<[T]> in particular, but theoretically any pointer type around a [T] could be used. However, array patterns still match on &[T], &mut [T], and [T; n] only, meaning that to match on a Box<[T]>, one must first convert it to a slice, which disallows moves. This may prove to significantly limit the amount of useful code that can be written using array patterns.

Another problem with today’s array patterns is in subslice matching, which specifies that the rest of a slice not matched on already in the pattern should be put into a variable:

let foo = [1i, 2, 3];
match foo {
    [head, tail..] => {
        assert_eq!(head, 1);
        assert_eq!(tail, &[2, 3]);
    },
    _ => {},
}

This makes sense, but still has a few problems. In particular, tail is a &[int], even though the compiler can always assert that it will have a length of 2, so there is no way to treat it like a fixed-length array. Also, all other bindings in array patterns are by-value, whereas bindings using subslice matching are by-reference (even though they don’t use ref). This can create confusing errors because of the fact that the .. syntax is the only way of taking a reference to something within a pattern without using the ref keyword.

Finally, the compiler currently complains when one tries to take multiple mutable references to different values within the same array in a slice pattern:

let foo: &mut [int] = &mut [1, 2, 3];
match foo {
    [ref mut a, ref mut b] => ...,
    ...
}

This fails to compile, because the compiler thinks that this would allow multiple mutable borrows to the same value (which is not the case).

Detailed design

Drawbacks

Alternatives

Unresolved questions