about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-01-18 19:36:01 +0100
committerGitHub <noreply@github.com>2020-01-18 19:36:01 +0100
commit733c7f440e7777f35bb527f8b75cb9351d31c14d (patch)
treeed56c35363f50a9d0283e01959fe52430e43fb98
parent779f85bac6b304dd4cad5981acf053a2c0601582 (diff)
parent57b6843100b247b6065b71e4485572dda4bfccc6 (diff)
downloadrust-733c7f440e7777f35bb527f8b75cb9351d31c14d.tar.gz
rust-733c7f440e7777f35bb527f8b75cb9351d31c14d.zip
Rollup merge of #67712 - Centril:stabilize-slice_patterns, r=matthewjasper
Stabilize `#![feature(slice_patterns)]` in 1.42.0

# Stabilization report

The following is the stabilization report for `#![feature(slice_patterns)]`.
This report is the collaborative effort of @matthewjasper and @Centril.

Tracking issue: https://github.com/rust-lang/rust/issues/62254
[Version target](https://forge.rust-lang.org/#current-release-versions): 1.42 (2020-01-30 => beta, 2020-03-12 => stable).

## Backstory: slice patterns

It is already possible to use slice patterns on stable Rust to match on arrays and slices. For example, to match on a slice, you may write:

```rust
fn foo(slice: &[&str]) {
    match slice {
        [] => { dbg!() }
        [a] => { dbg!(a); }
        [a, b] => { dbg!(a, b); }
        _ => {}
    //  ^ Fallback -- necessary because the length is unknown!
    }
}
```

To match on an array, you may instead write:

```rust
fn bar([a, b, c]: [u8; 3]) {}
//     --------- Length is known, so pattern is irrefutable.
```

However, on stable Rust, it is not yet possible to match on a subslice or subarray.

## A quick user guide: Subslice patterns

The ability to match on a subslice or subarray is gated under `#![feature(slice_patterns)]` and is what is proposed for stabilization here.

### The syntax of subslice patterns

Subslice / subarray patterns come in two flavors syntactically.

Common to both flavors is they use the token `..`, referred as a *"rest pattern"* in a pattern context. This rest pattern functions as a variable-length pattern, matching whatever amount of elements that haven't been matched already before and after.

When `..` is used syntactically as an element of a slice-pattern, either directly (1), or as part of a binding pattern (2), it becomes a subslice pattern.

On stable Rust, a rest pattern `..` can also be used in a tuple or tuple-struct pattern with `let (x, ..) = (1, 2, 3);` and `let TS(x, ..) = TS(1, 2, 3);` respectively.

### (1) Matching on a subslice without binding it

```rust
fn base(string: &str) -> u8 {
    match string.as_bytes() {
        [b'0', b'x', ..] => 16,
        [b'0', b'o', ..] => 8,
        [b'0', b'b', ..] => 2,
        _ => 10,
    }
}

fn main() {
    assert_eq!(base("0xFF"), 16);
    assert_eq!(base("0x"), 16);
}
```

In the function `base`, the pattern `[b'0', b'x', ..]` will match on any byte-string slice with the *prefix* `0x`. Note that `..` may match on nothing, so `0x` is a valid match.

### (2) Binding a subslice:

```rust
fn main() {
    #[derive(PartialEq, Debug)]
    struct X(u8);
    let xs: Vec<X> = vec![X(0), X(1), X(2)];

    if let [start @ .., end] = &*xs {
        //              --- bind on last element, assuming there is one.
        //  ---------- bind the initial elements, if there are any.
        assert_eq!(start, &[X(0), X(1)] as &[X]);
        assert_eq!(end, &X(2));
        let _: &[X] = start;
        let _: &X = end;
    }
}
```

In this case, `[start @ .., end]`  will match any non-empty slice, binding the last element to `end` and any elements before that to `start`. Note in particular that, as above, `start` may match on the empty slice.

### Only one `..` per slice pattern

In today's stable Rust, a tuple (struct) pattern `(a, b, c)` can only have one subtuple pattern (e.g., `(a, .., c)`). That is, if there is a rest pattern, it may only occur once. Any `..` that follow, as in e.g., `(a, .., b, ..)` will cause an error, as there is no way for the compiler to know what `b` applies to. This rule also applies to slice patterns. That is, you may also not write `[a, .., b, ..]`.

## Motivation

[PR #67569]: https://github.com/rust-lang/rust/pull/67569/files

Slice patterns provide a natural and efficient way to pattern match on slices and arrays. This is particularly useful as slices and arrays are quite a common occurence in modern software targeting modern hardware. However, as aforementioned, it's not yet possible to perform incomplete matches, which is seen in `fn base`, an example taken from the `rustc` codebase itself. This is where subslice patterns come in and extend slice patterns with the natural syntax `xs @ ..` and `..`, where the latter is already used for tuples and tuple structs. As an example of how subslice patterns can be used to clean up code, we have [PR #67569]. In this PR, slice patterns enabled us to improve readability and reduce unsafety, at no loss to performance.

## Technical specification

### Grammar

The following specification is a *sub-set* of the grammar necessary to explain what interests us here. Note that stabilizing subslice patterns does not alter the stable grammar. The stabilization contains purely semantic changes.

```rust
Binding = reference:"ref"? mutable:"mut"? name:IDENT;

Pat =
  | ... // elided
  | Rest: ".."
  | Binding:{ binding:Binding { "@" subpat:Pat }? }
  | Slice:{ "[" elems:Pat* %% "," "]" }
  | Paren:{ "(" pat:Pat ")" }
  | Tuple:{ path:Path? "(" elems:Pat* &% "," ")" }
  ;
```

Notes:

1. `(..)` is interpreted as a `Tuple`, not a `Paren`.
   This means that `[a, (..)]` is interpreted as `Slice[Binding(a), Tuple[Rest]]` and not `Slice[Binding(a), Paren(Rest)]`.

### Name resolution

[resolve_pattern_inner]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.LateResolutionVisitor.html#method.resolve_pattern_inner
[product context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/enum.PatBoundCtx.html#variant.Product

A slice pattern is [resolved][resolve_pattern_inner] as a [product context] and `..` is given no special treatment.

### Abstract syntax of slice patterns

The abstract syntax (HIR level) is defined like so:

```rust
enum PatKind {
    ... // Other unimportant stuff.
    Wild,
    Binding {
        binding: Binding,
        subpat: Option<Pat>,
    },
    Slice {
        before: List<Pat>,
        slice: Option<Pat>,
        after: List<Pat>,
    },
}
```

[`hir::PatKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/enum.PatKind.html

The executable definition is found in [`hir::PatKind`].

### Lowering to abstract syntax

Lowering a slice pattern to its abstract syntax proceeds by:

1. Lowering each element pattern of the slice pattern, where:

    1. `..` is lowered to `_`,
       recording that it was a subslice pattern,

    2. `binding @ ..` is lowered to `binding @ _`,
       recording that it was a subslice pattern,

    3. and all other patterns are lowered as normal,
       recording that it was not a subslice pattern.

2. Taking all lowered elements until the first subslice pattern.

3. Take all following elements.

   If there are any,

      1. The head is the sub-`slice` pattern.
      2. The tail (`after`) must not contain a subslice pattern,
         or an error occurs.

[`LoweringContext::lower_pat_slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/lowering/struct.LoweringContext.html#method.lower_pat_slice

The full executable definition can be found in [`LoweringContext::lower_pat_slice`].

### Type checking slice patterns

#### Default binding modes

[non-reference pattern]: https://doc.rust-lang.org/nightly/reference/patterns.html#binding-modes
[`is_non_ref_pat`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/struct.FnCtxt.html#method.is_non_ref_pat
[peel_off_references]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/struct.FnCtxt.html#method.peel_off_references

A slice pattern is a [non-reference pattern] as defined in [`is_non_ref_pat`]. This means that when type checking a slice pattern, as many immediate reference types are [peeled off][peel_off_references] from the `expected` type as possible and the default binding mode is adjusted to by-reference before checking the slice pattern. See https://github.com/rust-lang/rust/pull/63118/#issuecomment-524161584 for an algorithmic description.

[RFC 2359]: https://github.com/rust-lang/rfcs/blob/master/text/2359-subslice-pattern-syntax.md

[rfc-2359-gle]: https://github.com/rust-lang/rfcs/blob/master/text/2359-subslice-pattern-syntax.md#guide-level-explanation

See [RFC 2359]'s [guide-level explanation][rfc-2359-gle] and the tests listed below for examples of what effect this has.

#### Checking the pattern

Type checking a slice pattern proceeds as follows:

1. Resolve any type variables by a single level.
   If the result still is a type variable, error.

2. Determine the expected type for any subslice pattern (`slice_ty`) and for elements (`inner_ty`) depending on the expected type.

   1. If the expected type is an array (`[E; N]`):

      1. Evaluate the length of the array.
         If the length couldn't be evaluated, error.
         This may occur when we have e.g., `const N: usize`.
         Now `N` is known.

      2. If there is no sub-`slice` pattern,
         check `len(before) == N`,
         and otherwise error.

      3. Otherwise,
         set `S = N - len(before) - len(after)`,
         and check `N >= 0` and otherwise error.
         Set `slice_ty = [E; S]`.

      Set `inner_ty = E`.

   2. If the expected type is a slice (`[E]`),
      set `inner_ty = E` and `slice_ty = [E]`.

   3. Otherwise, error.

3. Check each element in `before` and `after` against `inner_ty`.
4. If it exists, check `slice` against `slice_ty`.

[`check_pat_slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/struct.FnCtxt.html#method.check_pat_slice

For an executable definition, see [`check_pat_slice`].

### Typed abstract syntax of slice and array patterns

The typed abstract syntax (HAIR level) is defined like so:

```rust
enum PatKind {
    ... // Other unimportant stuff.
    Wild,
    Binding {
        ... // Elided.
    }
    Slice {
        prefix: List<Pat>,
        slice: Option<Pat>,
        suffix: List<Pat>,
    },
    Array {
        prefix: List<Pat>,
        slice: Option<Pat>,
        suffix: List<Pat>,
    },
}
```

[`hair::pattern::PatKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/hair/pattern/enum.PatKind.html

The executable definition is found in [`hair::pattern::PatKind`].

### Lowering to typed abstract syntax

Lowering a slice pattern to its typed abstract syntax proceeds by:

1. Lowering each pattern in `before` into `prefix`.
2. Lowering the `slice`, if it exists, into `slice`.
   1. A `Wild` pattern in abstract syntax is lowered to `Wild`.
   2. A `Binding` pattern in abstract syntax is lowered to `Binding { .. }`.
3. Lowering each pattern in `after` into `after`.
4. If the type is `[E; N]`, construct `PatKind::Array { prefix, slice, after }`, otherwise `PatKind::Slice { prefix, slice, after }`.

[`PatCtxt::slice_or_array_pattern`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/hair/pattern/struct.PatCtxt.html#method.slice_or_array_pattern

The executable definition is found in [`PatCtxt::slice_or_array_pattern`].

### Exhaustiveness checking

Let `E` be the element type of a slice or array.

- For array types, `[E; N]` with a known length `N`, the full set of constructors required for an exahustive match is the sequence `ctors(E)^N` where `ctors` denotes the constructors required for an exhaustive match of `E`.

- Otherwise, for slice types `[E]`, or for an array type with an unknown length `[E; ?L]`, the full set of constructors is the infinite sequence `⋃_i=0^∞ ctors(E)^i`. This entails that an exhaustive match without a cover-all pattern (e.g. `_` or `binding`) or a subslice pattern (e.g., `[..]` or `[_, _, ..]`) is impossible.

- `PatKind::{Slice, Array}(prefix, None, suffix @ [])` cover a sequence of of `len(prefix)` covered by `patterns`. Note that `suffix.len() > 0` with `slice == None` is unrepresentable.

- `PatKind::{Slice, Array}(prefix, Some(s), suffix)` cover a `sequence` with `prefix` as the start and `suffix` as the end and where `len(prefix) + len(suffix) <= len(sequence)`. The `..` in the middle is interpreted as an unbounded number of `_`s in terms of exhaustiveness checking.

### MIR representation

The relevant MIR representation for the lowering into MIR, which is discussed in the next section, includes:

```rust
enum Rvalue {
    // ...
    /// The length of a `[X]` or `[X; N]` value.
    Len(Place),
}

struct Place {
    base: PlaceBase,
    projection: List<PlaceElem>,
}

enum ProjectionElem {
    // ...
    ConstantIndex {
        offset: Nat,
        min_length: Nat,
        from_end: bool,
    },
    Subslice {
        from: Nat,
        to: Nat,
        from_end: bool,
    },
}
```

### Lowering to MIR

* For a slice pattern matching a slice, where the pattern has `N` elements specified, there is a check that the `Rvalue::Len` of the slice is at least `N` to decide if the pattern can match.

* There are two kinds of `ProjectionElem` used for slice patterns:

    1. `ProjectionElem::ConstantIndex` is an array or slice element with a known index. As a shorthand it's written `base[offset of min_length]` if `from_end` is false and `base[-offset of min_length]` if `from_end` is true. `base[-offset of min_length]` is the `len(base) - offset`th element of `base`.

    2. `ProjectionElem::Subslice` is a subslice of an array or slice with known bounds. As a shorthand it's written `base[from..to]` if `from_end` is false and `base[from:-to]` if `from_end` is true. `base[from:-to]` is the subslice `base[from..len(base) - to]`.

    * Note that `ProjectionElem::Index` is used for indexing expressions, but not for slice patterns. It's written `base[idx]`.

* When binding an array pattern, any individual element binding is lowered to an assignment or borrow of `base[offset of len]` where `offset` is the element's index in the array and `len` is the array's length.

* When binding a slice pattern, let `N` be the number of elements that have patterns. Elements before the subslice pattern (`prefix`) are lowered to `base[offset of N]` where `offset` is the element's index from the start. Elements after the subslice pattern (`suffix`) are lowered to `base[-offset of N]` where `offset` is the element's index from the end, plus 1.

* Subslices of arrays are lowered to `base[from..to]` where `from` is the number of elements before the subslice pattern and `to = len(array) - len(suffix)` is the length of the array minus the number of elements after the subslice pattern.

* Subslices of slices are lowered to `base[from:-to]` where `from` is the number of elements before the subslice pattern (`len(prefix)`) and `to` is the number of elements after the subslice pattern (`len(suffix)`).

### Safety and const checking

* Subslice patterns do not introduce any new unsafe operations.

* As subslice patterns for arrays are irrefutable, they are allowed in const contexts. As are `[..]` and `[ref y @ ..]` patterns for slices. However, `ref mut` bindings are only allowed with `feature(const_mut_refs)` for now.

* As other subslice patterns for slices require a `match`, `if let`, or `while let`, they are only allowed with `feature(const_if_match, const_fn)` for now.

* Subslice patterns may occur in promoted constants.

### Borrow and move checking

* A subslice pattern can be moved from if it has an array type `[E; N]` and the parent array can be moved from.

* Moving from an array subslice pattern moves from all of the elements of the array within the subslice.

    * If the subslice contains at least one element, this means that dynamic indexing (`arr[idx]`) is no longer allowed on the array.

    * The array can be reinitialized and can still be matched with another slice pattern that uses a disjoint set of elements.

* A subslice pattern can be mutably borrowed if the parent array/slice can be mutably borrowed.

* When determining whether an access conflicts with a borrow and at least one is a slice pattern:

    * `x[from..to]` always conflicts with `x` and `x[idx]` (where `idx` is a variable).

    * `x[from..to]` conflicts with `x[idx of len]` if `from <= idx` and `idx < to` (that is, `idx ∈ from..to`).

    * `x[from..to]` conflicts with `x[from2..to2]` if `from < to2` and `from2 < to` (that is, `(from..to) ∩ (from2..to2) ≠ ∅`).

    * `x[from:-to]` always conflicts with `x`, `x[idx]`, and `x[from2:-to2]`.

    * `x[from:-to]` conflicts with `x[idx of len]` if `from <= idx`.

    * `x[from:-to]` conflicts with `x[-idx of len]` if `to < idx`.

* A constant index from the end conflicts with other elements as follows:

    * `x[-idx of len]` always conflicts with `x` and `x[idx]`.

    * `x[-idx of len]` conflicts with `x[-idx2 of len2]` if `idx == idx2`.

    * `x[-idx of len]` conflicts with `x[idx2 of len2]` if `idx + idx2 >= max(len, len2)`.

## Tests

The tests can be primarily seen in the PR itself. Here are some of them:

### Parsing (3)

* Testing that `..` patterns are syntactically allowed in all pattern contexts (2)
    * [pattern/rest-pat-syntactic.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/rest-pat-syntactic.rs)
    * [ignore-all-the-things.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/ignore-allthe-things.rs)

* Slice patterns allow a trailing comma, including after `..` (1)
    * [trailing-comma.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/trailing-comma.rs)

### Lowering (2)

* `@ ..` isn't allowed outside of slice patterns and only allowed once in each pattern (1)
    * [pattern/rest-pat-semantic-disallowed.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/rest-pat-semantic-disallowed.rs)

* Mulitple `..` patterns are not allowed (1)
    * [parser/match-vec-invalid.rs](https://github.com/rust-lang/rust/blob/53712f8637dbe326df569a90814aae1cc5429710/src/test/ui/parser/match-vec-invalid.rs)

### Type checking (5)

* Default binding modes apply to slice patterns (2)
    * [rfc-2005-default-binding-mode/slice.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/rfc-2005-default-binding-mode/slice.rs)
    * [rfcs/rfc-2005-default-binding-mode/slice.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs)

* Array patterns cannot have more elements in the pattern than in the array (2)
    * [match/match-vec-mismatch.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/match/match-vec-mismatch.rs)
    * [error-codes/E0528.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/error-codes/E0528.rs)

* Array subslice patterns have array types (1)
    * [array-slice-vec/subslice-patterns-pass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-pass.rs)

### Exhaustiveness and usefulness checking (20)

* Large subslice matches don't stack-overflow the exhaustiveness checker (1)
    * [pattern/issue-53820-slice-pattern-large-array.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs)

* Array patterns with subslices are irrefutable (1)
    * [issues/issue-7784.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-7784.rs)

* `[xs @ ..]` slice patterns are irrefutable (1)
    * [binding/irrefutable-slice-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/irrefutable-slice-patterns.rs)

* Subslice patterns can match zero-length slices (2)
    * [issues/issue-15080.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-15080.rs)
    * [issues/issue-15104.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-15104.rs)

* General tests (13)
    * [issues/issue-12369.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-12369.rs)
    * [issues/issue-37598.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-37598.rs)
    * [pattern/usefulness/match-vec-unreachable.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/match-vec-unreachable.rs)
    * [pattern/usefulness/non-exhaustive-match.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/non-exhaustive-match.rs)
    * [pattern/usefulness/non-exhaustive-match-nested.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs)
    * [pattern/usefulness/non-exhaustive-pattern-witness.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs)
    * [pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs)
    * [pattern/usefulness/match-byte-array-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs)
    * [pattern/usefulness/match-slice-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/match-slice-patterns.rs)
    * [pattern/usefulness/slice-patterns-exhaustiveness.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs)
    * [pattern/usefulness/slice-patterns-irrefutable.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs)
    * [pattern/usefulness/slice-patterns-reachability.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs)
    * [uninhabited/uninhabited-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/uninhabited/uninhabited-patterns.rs)

* Interactions with or-patterns (2)
    * [or-patterns/exhaustiveness-pass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/or-patterns/exhaustiveness-pass.rs)
    * [or-patterns/exhaustiveness-unreachable-pattern.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs)

### Borrow checking (28)

* Slice patterns can only move from owned, fixed-length arrays (4)
    * [borrowck/borrowck-move-out-of-vec-tail.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs)
    * [moves/move-out-of-slice-2.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/moves/move-out-of-slice-2.rs)
    * [moves/move-out-of-array-ref.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/moves/move-out-of-array-ref.rs)
    * [issues/issue-12567.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-12567.rs)

* Moves from arrays are tracked by element (2)
    * [borrowck/borrowck-move-out-from-array-no-overlap.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs)
    * [borrowck/borrowck-move-out-from-array-use-no-overlap.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs)

* Slice patterns cannot be used on moved-from slices/arrays (2)
    * [borrowck/borrowck-move-out-from-array.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-move-out-from-array.rs)
    * [borrowck/borrowck-move-out-from-array-use.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs)

* Slice patterns cannot be used with conflicting borrows (3)
    * [borrowck/borrowck-describe-lvalue.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-describe-lvalue.rs)
    * [borrowck/borrowck-slice-pattern-element-loan-array.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs)
    * [borrowck/borrowck-slice-pattern-element-loan-slice.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs)

* Borrows from slice patterns are tracked and only conflict when there is possible overlap (6)
    * [borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs)
    * [borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs)
    * [borrowck/borrowck-slice-pattern-element-loan-rpass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs)
    * [borrowck/borrowck-vec-pattern-element-loan.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs)
    * [borrowck/borrowck-vec-pattern-loan-from-mut.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs)
    * [borrowck/borrowck-vec-pattern-tail-element-loan.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs)

* Slice patterns affect indexing expressions (1)
    * [borrowck/borrowck-vec-pattern-move-tail.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs)

* Borrow and move interactions with `box` patterns (1)
    * [borrowck/borrowck-vec-pattern-move-tail.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs)

* Slice patterns correctly affect inference of closure captures (2)
    * [borrowck/borrowck-closures-slice-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs)
    * [borrowck/borrowck-closures-slice-patterns-ok.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs)

* Interactions with `#![feature(bindings_after_at)]` (7)
    * [pattern/bindings-after-at/borrowck-move-and-move.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs)
    * [pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs)
    * [pattern/bindings-after-at/borrowck-pat-at-and-box.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs)
    * [pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs)
    * [pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs)
    * [pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs)
    * [pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs)

* Misc (1)
    * [issues/issue-26619.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-26619.rs)

### MIR lowering (1)

* [uniform_array_move_out.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/mir-opt/uniform_array_move_out.rs)

### Evaluation (19)

* Slice patterns don't cause leaks or double drops (2)
    * [drop/dynamic-drop.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/drop/dynamic-drop.rs)
    * [drop/dynamic-drop-async.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/drop/dynamic-drop-async.rs)

* General run-pass tests (10)
    * [array-slice-vec/subslice-patterns-pass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-pass.rs)
    * [array-slice-vec/vec-matching-fixed.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/vec-matching-fixed.rs)
    * [array-slice-vec/vec-matching-fold.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/vec-matching-fold.rs)
    * [array-slice-vec/vec-matching-legal-tail-element-borrow.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs)
    * [array-slice-vec/vec-matching.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/vec-matching.rs)
    * [array-slice-vec/vec-tail-matching.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/vec-tail-matching.rs)
    * [binding/irrefutable-slice-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/irrefutable-slice-patterns.rs)
    * [binding/match-byte-array-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/match-byte-array-patterns.rs)
    * [binding/match-vec-alternatives.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/match-vec-alternatives.rs)
    * [borrowck/borrowck-slice-pattern-element-loan-rpass.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs)

* Matching a large by-value array (1)
    * [issues/issue-17877.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/issues/issue-17877.rs)

* Uninhabited elements (1)
    * [binding/empty-types-in-patterns.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/empty-types-in-patterns.rs)

* Zero-sized elements (3)
    * [binding/zero_sized_subslice_match.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/binding/zero_sized_subslice_match.rs)
    * [array-slice-vec/subslice-patterns-const-eval.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs)
    * [array-slice-vec/subslice-patterns-const-eval-match.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs)

* Evaluation in const contexts (2)
    * [array-slice-vec/subslice-patterns-const-eval.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs)
    * [array-slice-vec/subslice-patterns-const-eval-match.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs)

## Misc (1)

* Exercising a case where const-prop cased an ICE (1)
    * [consts/const_prop_slice_pat_ice.rs](https://github.com/rust-lang/rust/blob/acb6690e1d58fc5f262ada5b5030fe73e601f1e8/src/test/ui/consts/const_prop_slice_pat_ice.rs)

## History

- 2012-12-08, commit https://github.com/rust-lang/rust/commit/1968cb315af9d128ee4457738fddd1eba275277f
  Author: Jakub Wieczorek
  Reviewers: @graydon

  This is where slice patterns were first implemented. It is particularly instructive to read the `vec-tail-matching.rs` test.

- 2013-08-20, issue https://github.com/rust-lang/rust/issues/8636
  Author: @huonw
  Fixed by @mikhail-m1 in https://github.com/rust-lang/rust/pull/51894

  The issue describes a problem wherein the borrow-checker would not consider disjointness when checking mutable references in slice patterns.

- 2014-09-03, RFC https://github.com/rust-lang/rfcs/pull/164
  Author: @brson
  Reviewers: The Core Team

  The RFC decided to feature gate slice patterns due to concerns over lack of oversight and the exhaustiveness checking logic not having seen much love. Since then, the exhaustivenss checking algorithm, in particular for slice patterns, has been substantially refactored and tests have been added.

- 2014-09-03, RFC https://github.com/rust-lang/rfcs/pull/202
  Author: @krdln
  Reviewers: The Core Team

  > Change syntax of subslices matching from `..xs` to `xs..` to be more consistent with the rest of the language and allow future backwards compatible improvements.

  In 2019, https://github.com/rust-lang/rfcs/pull/2359 changed the syntax again in favor of `..` and `xs @ ..`.

- 2014-09-08, PR https://github.com/rust-lang/rust/pull/17052
  Author: @pcwalton
  Reviewers: @alexcrichton and @sfackler

  This implemented the feature gating as specified in https://github.com/rust-lang/rfcs/pull/164.

- 2015-03-06, RFC https://github.com/rust-lang/rfcs/pull/495
  Author: @P1start
  Reviewers: The Core Team

  The RFC changed array and slice patterns like so:

  - Made them only match on arrays (`[T; N]`) and slice types (`[T]`), not references to slice types (`& mut? [T]`).
  - Made subslice matching yield a value of type `[T; N]` or `[T]`, not `& mut? [T]`.
  - Allowed multiple mutable references to be made to different parts of the same array or slice in array patterns.

  These changes were made to fit with the introduction of DSTs like `[T]` as well as with e.g. `box [a, b, c]` (`Box<[T]>`) in the future. All points remain true today, in particular with the advent of default binding modes.

- 2015-03-22, PR https://github.com/rust-lang/rust/pull/23361
  Author: @petrochenkov
  Reviewers: Unknown

  The PR adjusted codegen ("trans") such that `let ref a = *"abcdef"` would no longer ICE, paving the way for https://github.com/rust-lang/rfcs/pull/495.

- 2015-05-28, PR https://github.com/rust-lang/rust/pull/23794
  Author: @brson
  Reviewers: @nrc

  The PR feature gated slice patterns in more contexts.

- 2016-06-09, PR https://github.com/rust-lang/rust/pull/32202
  Author: @arielb1
  Reviewers: @eddyb and @nikomatsakis

  This implemented RFC https://github.com/rust-lang/rfcs/pull/495 via a MIR based implementation fixing some bugs.

- 2016-09-16, PR https://github.com/rust-lang/rust/pull/36353
  Author: @arielb1
  Reviewers: @nagisa, @pnkfelix, and @nikomatsakis

  The PR made move-checker improvements prohibiting moves out of slices.

- 2018-02-17, PR https://github.com/rust-lang/rust/pull/47926
  Author: @mikhail-m1
  Reviewers: @nikomatsakis

  This added the `UniformArrayMoveOut` which converted move-out-from-array by `Subslice` and `ConstIndex {.., from_end: true }` to `ConstIndex` move out(s) from the beginning of the array. This fixed some problems with the MIR borrow-checker and drop-elaboration of arrays.

  Unfortunately, the transformation ultimately proved insufficient for soundness and was removed and replaced in https://github.com/rust-lang/rust/pull/66650.

- 2018-02-19, PR https://github.com/rust-lang/rust/pull/48355
  Author: @mikhail-m1
  Reviewers: @nikomatsakis

  After https://github.com/rust-lang/rust/pull/47926, this restored some MIR optimizations after drop-elaboration and borrow-checking.

- 2018-03-20, PR https://github.com/rust-lang/rust/pull/48516
  Author: @petrochenkov
  Reviewers: @nikomatsakis

  This stabilized fixed length slice patterns `[a, b, c]` without variable length subslices and moved subslice patterns into `#![feature(slice_patterns)`. See https://github.com/rust-lang/rust/issues/48836 wherein the language team accepted the proposal to stabilize.

- 2018-07-06, PR https://github.com/rust-lang/rust/pull/51894
  Author: @mikhail-m1
  Reviewers: @nikomatsakis

  https://github.com/rust-lang/rust/issues/8636 was fixed such that the borrow-checker would consider disjointness with respect to mutable references in slice patterns.

- 2019-06-30, RFC https://github.com/rust-lang/rfcs/pull/2359
  Author: @petrochenkov
  Reviewers: The Language Team

  The RFC switched the syntax of subslice patterns to `{$binding @}? ..` as opposed to `.. $pat?` (which was what the RFC originally proposed). This RFC reignited the work towards finishing the implementation and the testing of slice patterns which eventually lead to this stabilization proposal.

- 2019-06-30, RFC https://github.com/rust-lang/rfcs/pull/2707
  Author: @petrochenkov
  Reviewers: The Language Team

  This RFC built upon https://github.com/rust-lang/rfcs/pull/2359 turning `..` into a full-fledged pattern (`Pat |= Rest:".." ;`), as opposed to a special part of slice and tuple patterns, moving previously syntactic restrictions into semantic ones.

- 2019-07-03, PR https://github.com/rust-lang/rust/pull/62255
  Author: @Centril
  Reviewers: @varkor

  This closed the old tracking issue (https://github.com/rust-lang/rust/issues/23121) in favor of the new one (https://github.com/rust-lang/rust/issues/62254) due to the new RFCs having been accepted.

- 2019-07-28, PR https://github.com/rust-lang/rust/pull/62550
  Author: @Centril
  Reviewers: @petrochenkov and @eddyb

  Implemented RFCs https://github.com/rust-lang/rfcs/pull/2707 and https://github.com/rust-lang/rfcs/pull/2359 by introducing the `..` syntactic rest pattern form as well as changing the lowering to subslice and subtuple patterns and the necessary semantic restrictions as per the RFCs.

  Moreover, the parser was cleaned up to use a more generic framework for parsing sequences of things. This framework was employed in parsing slice patterns.

  Finally, the PR introduced parser recovery for half-open ranges (e.g., `..X`, `..=X`, and `X..`), demonstrating in practice that the RFCs proposed syntax will enable half-open ranges if we want to add those (which is done in https://github.com/rust-lang/rust/pull/67258).

- 2019-07-30, PR https://github.com/rust-lang/rust/pull/63111
  Author: @Centril
  Reviewers: @estebank

  Added a test which comprehensively exercised the parsing of `..` rest patterns. That is, the PR exercised the specification in https://github.com/rust-lang/rfcs/pull/2707. Moreover, a test was added for the semantic restrictions noted in the RFC.

- 2019-07-31, PR https://github.com/rust-lang/rust/pull/63129
  Author: @Centril
  Reviewers: @oli-obk

  Hardened the test-suite for subslice and subarray patterns with a run-pass tests. This test exercises both type checking and dynamic semantics.

- 2019-09-15, PR https://github.com/rust-analyzer/rust-analyzer/pull/1848
  Author: @ecstatic-morse
  Reviewers: @matklad

  This implemented the syntactic change (rest patterns, `..`) in rust-analyzer.

- 2019-11-05, PR https://github.com/rust-lang/rust/pull/65874
  Author: @Nadrieril
  Reviewers: @varkor, @arielb1, and @Centril

  Usefulness / exhaustiveness checking saw a major refactoring clarifying the analysis by emphasizing that each row of the matrix can be seen as a sort of stack from which we pop constructors.

- 2019-11-12, PR https://github.com/rust-lang/rust/pull/66129
  Author: @Nadrieril
  Reviewers: @varkor, @Centril, and @estebank

  Usefulness / exhaustiveness checking of slice patterns were refactored in favor of clearer code. Before the PR, variable-length slice patterns were eagerly expanded into a union of fixed-length slices. They now have their own special constructor, which allows expanding them more lazily. As a side-effect, this improved diagnostics. Moreover, the test suite for exhaustiveness checking of slice patterns was hardened.

- 2019-11-20, PR https://github.com/rust-lang/rust/pull/66497
  Author: @Nadrieril
  Reviewers: @varkor and @Centril

  Building on the previous PR, this one fixed a bug https://github.com/rust-lang/rust/issues/53820 wherein sufficiently large subarray patterns (`match [0u8; 16*1024] { [..] => {}}`) would result in crashing the compiler with a stack-overflow. The PR did this by treating array patterns in a more first-class way (using a variable-length mechanism also used for slices) rather than like large tuples. This also had the effect of improving diagnostics for non-exhaustive matches.

- 2019-11-28, PR https://github.com/rust-lang/rust/pull/66603
  Author: @Nadrieril
  Reviewers: @varkor

  Fixed a bug https://github.com/rust-lang/rust/issues/65413 wherein constants, slice patterns, and exhaustiveness checking interacted in a suboptimal way conspiring to suggest that a reachable arm was in fact unreachable.

- 2019-12-12, PR https://github.com/rust-lang/rust/pull/66650
  Author: @matthewjasper
  Reviewers: @pnkfelix and @Centril

  Removed the `UniformArrayMoveOut` MIR transformation pass in favor of baking the necessary logic into the borrow-checker, drop elaboration and MIR building itself. This fixed a number of bugs, including a soundness hole https://github.com/rust-lang/rust/issues/66502. Moreover, the PR added a slew of tests for borrow- and move-checking of slice patterns as well as a test for the dynamic semantics of dropping subslice patterns.

- 2019-12-16, PR https://github.com/rust-lang/rust/pull/67318
  Author: @Centril
  Reviewers: @matthewjasper

  Improved documentation for AST->HIR lowering + type checking of slice as well as minor code simplification.

- 2019-12-21, PR https://github.com/rust-lang/rust/pull/67467
  Author: @matthewjasper
  Reviewers: @oli-obk, @RalfJung, and @Centril

  Fixed bugs in the const evaluation of slice patterns and added tests for const evaluation as well as borrow- and move-checking.

- 2019-12-22, PR https://github.com/rust-lang/rust/pull/67439
  Author: @Centril
  Reviewers: @matthewjasper

  Cleaned up HAIR lowering of slice patterns, removing special cased dead code for the unrepresentable `[a, b] @ ..`. The PR also refactored type checking for slice patterns.

- 2019-12-23, PR https://github.com/rust-lang/rust/pull/67546
  Author: @oli-obk
  Reviewers: @varkor and @RalfJung

  Fixed an ICE in the MIR interpretation of slice patterns.

- 2019-12-24, PR https://github.com/rust-lang/rust/pull/66296
  Author: @Centril
  Reviewers: @pnkfelix and @matthewjasper

  This implemented `#![feature(bindings_after_at)]` which allows writing e.g. `a @ Some([_, b @ ..])`. This is not directly linked to slice patterns other than with patterns in general. However, the combination of the feature and `slice_patterns` received some testing in the PR.

- 2020-01-09, PR https://github.com/rust-lang/rust/pull/67990
  Author: @Centril
  Reviewers: @matthewjasper

  This hardened move-checker tests for `match` expressions in relation to https://github.com/rust-lang/rust/issues/53114.

- This PR stabilizes `slice_patterns`.

## Related / possible future work

There is on-going work to improve pattern matching in other ways (the relevance of some of these are indirect, and only by composition):

- OR-patterns, `pat_0 | .. | pat_n` is almost implemented.
  Tracking issue: https://github.com/rust-lang/rust/issues/54883

- Bindings after `@`, e.g., `x @ Some(y)` is implemented.
  Tracking issue: https://github.com/rust-lang/rust/issues/65490

- Half-open range patterns, e.g., `X..`, `..X`, and `..=X` as well as exclusive range patterns, e.g., `X..Y`.
  Tracking issue: https://github.com/rust-lang/rust/issues/67264 and https://github.com/rust-lang/rust/issues/37854
  The relevance here is that this work demonstrates, in practice, that there are no syntactic conflicts introduced by the stabilization of subslice patterns.

As for more direct improvements to slice patterns, some avenues could be:

- Box patterns, e.g., `box [a, b, .., c]` to match on `Box<[T]>`.
  Tracking issue: https://github.com/rust-lang/rust/issues/29641
  This issue currently has no path to stabilization.

  Note that it is currently possible to match on `Box<[T]>` or `Vec<T>` by first dereferencing them to slices.

- `DerefPure`, which would allow e.g., using slice patterns to match on `Vec<T>` (e.g., moving out of it).

Another idea which was raised by [RFC 2707](https://github.com/rust-lang/rfcs/blob/master/text/2707-dotdot-patterns.md#future-possibilities) and [RFC 2359](https://github.com/rust-lang/rfcs/blob/master/text/2359-subslice-pattern-syntax.md#pat-vs-pat) was to allow binding a subtuple pattern. That is, we could allow `(a, xs @ .., b)`. However, while we could allow by-value bindings to `..` as in `xs @ ..` at zero cost, the same cannot be said of by-reference bindings, e.g. `(a, ref xs @ .., b)`. The issue here becomes that for a reference to be legal, we have to represent `xs` contiguously in memory. In effect, we are forced into a [`HList`](https://docs.rs/frunk/0.3.1/frunk/hlist/struct.HCons.html) based representation for tuples.
-rw-r--r--src/doc/unstable-book/src/language-features/slice-patterns.md32
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/librustc/benches/lib.rs2
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc_ast_passes/feature_gate.rs21
-rw-r--r--src/librustc_ast_passes/lib.rs2
-rw-r--r--src/librustc_codegen_ssa/lib.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0527.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0528.md4
-rw-r--r--src/librustc_error_codes/error_codes/E0730.md2
-rw-r--r--src/librustc_feature/accepted.rs2
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir_build/lib.rs2
-rw-r--r--src/librustc_parse/lib.rs2
-rw-r--r--src/librustc_passes/lib.rs2
-rw-r--r--src/librustc_target/lib.rs2
-rw-r--r--src/librustc_ty/lib.rs2
-rw-r--r--src/librustc_typeck/lib.rs2
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/test/mir-opt/uniform_array_move_out.rs1
-rw-r--r--src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs (renamed from src/test/ui/match/match-vec-mismatch.rs)2
-rw-r--r--src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr (renamed from src/test/ui/match/match-vec-mismatch.stderr)10
-rw-r--r--src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs (renamed from src/test/ui/parser/match-vec-invalid.rs)2
-rw-r--r--src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr24
-rw-r--r--src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs2
-rw-r--r--src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs2
-rw-r--r--src/test/ui/array-slice-vec/subslice-patterns-pass.rs2
-rw-r--r--src/test/ui/array-slice-vec/vec-matching-fixed.rs2
-rw-r--r--src/test/ui/array-slice-vec/vec-matching-fold.rs2
-rw-r--r--src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs3
-rw-r--r--src/test/ui/array-slice-vec/vec-matching.rs2
-rw-r--r--src/test/ui/array-slice-vec/vec-tail-matching.rs2
-rw-r--r--src/test/ui/binding/empty-types-in-patterns.rs3
-rw-r--r--src/test/ui/binding/irrefutable-slice-patterns.rs3
-rw-r--r--src/test/ui/binding/match-byte-array-patterns.rs1
-rw-r--r--src/test/ui/binding/match-vec-alternatives.rs1
-rw-r--r--src/test/ui/binding/zero_sized_subslice_match.rs1
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs1
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr16
-rw-r--r--src/test/ui/borrowck/borrowck-describe-lvalue.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-describe-lvalue.stderr64
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-match.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr20
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr18
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr28
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr18
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr28
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-from-array.stderr20
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr16
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs3
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr22
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr6
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs4
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs1
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr16
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr2
-rw-r--r--src/test/ui/consts/const_prop_slice_pat_ice.rs1
-rw-r--r--src/test/ui/drop/dynamic-drop-async.rs1
-rw-r--r--src/test/ui/drop/dynamic-drop.rs7
-rw-r--r--src/test/ui/error-codes/E0528.rs2
-rw-r--r--src/test/ui/error-codes/E0528.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-slice-patterns.rs17
-rw-r--r--src/test/ui/feature-gates/feature-gate-slice-patterns.stderr57
-rw-r--r--src/test/ui/ignore-all-the-things.rs3
-rw-r--r--src/test/ui/issues/issue-12369.rs1
-rw-r--r--src/test/ui/issues/issue-12369.stderr4
-rw-r--r--src/test/ui/issues/issue-12567.rs2
-rw-r--r--src/test/ui/issues/issue-12567.stderr4
-rw-r--r--src/test/ui/issues/issue-15080.rs1
-rw-r--r--src/test/ui/issues/issue-15104.rs1
-rw-r--r--src/test/ui/issues/issue-17877.rs1
-rw-r--r--src/test/ui/issues/issue-23311.rs3
-rw-r--r--src/test/ui/issues/issue-26619.rs2
-rw-r--r--src/test/ui/issues/issue-26619.stderr2
-rw-r--r--src/test/ui/issues/issue-37598.rs1
-rw-r--r--src/test/ui/issues/issue-7784.rs1
-rw-r--r--src/test/ui/moves/move-out-of-array-ref.rs2
-rw-r--r--src/test/ui/moves/move-out-of-array-ref.stderr8
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs2
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-pass.rs2
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs2
-rw-r--r--src/test/ui/parser/match-vec-invalid.stderr42
-rw-r--r--src/test/ui/parser/pat-lt-bracket-6.rs1
-rw-r--r--src/test/ui/parser/pat-lt-bracket-6.stderr16
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr32
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr48
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr90
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs1
-rw-r--r--src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr64
-rw-r--r--src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs (renamed from src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs)4
-rw-r--r--src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs (renamed from src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs)2
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns.rs1
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr18
-rw-r--r--src/test/ui/pattern/usefulness/match-slice-patterns.rs2
-rw-r--r--src/test/ui/pattern/usefulness/match-slice-patterns.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-unreachable.rs1
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-unreachable.stderr8
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs2
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.rs1
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.stderr16
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs2
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr14
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs2
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr32
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs1
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-reachability.rs1
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr14
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/slice.rs2
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/slice.stderr2
-rw-r--r--src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs1
-rw-r--r--src/test/ui/trailing-comma.rs2
-rw-r--r--src/test/ui/uninhabited/uninhabited-patterns.rs2
142 files changed, 387 insertions, 666 deletions
diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md
deleted file mode 100644
index cdb74495884..00000000000
--- a/src/doc/unstable-book/src/language-features/slice-patterns.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# `slice_patterns`
-
-The tracking issue for this feature is: [#62254]
-
-[#62254]: https://github.com/rust-lang/rust/issues/62254
-
-------------------------
-
-The `slice_patterns` feature gate lets you use `..` to indicate any number of
-elements inside a pattern matching a slice. This wildcard can only be used once
-for a given array. If there's an pattern before the `..`, the subslice will be
-matched against that pattern. For example:
-
-```rust
-#![feature(slice_patterns)]
-
-fn is_symmetric(list: &[u32]) -> bool {
-    match list {
-        &[] | &[_] => true,
-        &[x, ref inside @ .., y] if x == y => is_symmetric(inside),
-        &[..] => false,
-    }
-}
-
-fn main() {
-    let sym = &[0, 1, 4, 2, 4, 1, 0];
-    assert!(is_symmetric(sym));
-
-    let not_sym = &[0, 1, 7, 2, 4, 1, 0];
-    assert!(!is_symmetric(not_sym));
-}
-```
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 15720ddcfc6..f77b4d7461e 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -133,7 +133,7 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 8c034938c2b..f0420247acf 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -19,7 +19,7 @@
 #![feature(range_is_empty)]
 #![feature(raw)]
 #![feature(saturating_neg)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
 #![feature(specialization)]
diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs
index ffb12f11c51..de82b262e49 100644
--- a/src/librustc/benches/lib.rs
+++ b/src/librustc/benches/lib.rs
@@ -1,4 +1,4 @@
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(test)]
 
 extern crate test;
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index b894aabd901..69ca4063694 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -42,7 +42,7 @@
 #![feature(optin_builtin_traits)]
 #![feature(option_expect_none)]
 #![feature(range_is_empty)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(thread_local)]
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 71cd66ddef4..461072873bb 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -470,29 +470,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_expr(self, e)
     }
 
-    fn visit_arm(&mut self, arm: &'a ast::Arm) {
-        visit::walk_arm(self, arm)
-    }
-
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
-            PatKind::Slice(pats) => {
-                for pat in &*pats {
-                    let span = pat.span;
-                    let inner_pat = match &pat.kind {
-                        PatKind::Ident(.., Some(pat)) => pat,
-                        _ => pat,
-                    };
-                    if inner_pat.is_rest() {
-                        gate_feature_post!(
-                            &self,
-                            slice_patterns,
-                            span,
-                            "subslice patterns are unstable"
-                        );
-                    }
-                }
-            }
             PatKind::Box(..) => {
                 gate_feature_post!(
                     &self,
diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs
index eadbc485296..5de45f4e1f3 100644
--- a/src/librustc_ast_passes/lib.rs
+++ b/src/librustc_ast_passes/lib.rs
@@ -2,7 +2,7 @@
 //! parsed by `rustc_parse` and then lowered, after the passes in this crate,
 //! by `rustc_ast_lowering`.
 
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 pub mod ast_validation;
 pub mod feature_gate;
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index ee527ecb509..aba77231268 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -4,7 +4,7 @@
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(libc)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
diff --git a/src/librustc_error_codes/error_codes/E0527.md b/src/librustc_error_codes/error_codes/E0527.md
index 4bff39dc770..97ea3126938 100644
--- a/src/librustc_error_codes/error_codes/E0527.md
+++ b/src/librustc_error_codes/error_codes/E0527.md
@@ -17,8 +17,6 @@ Ensure that the pattern is consistent with the size of the matched
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0528.md b/src/librustc_error_codes/error_codes/E0528.md
index 4b6ea246991..54c2c4d4e9d 100644
--- a/src/librustc_error_codes/error_codes/E0528.md
+++ b/src/librustc_error_codes/error_codes/E0528.md
@@ -4,8 +4,6 @@ matched array.
 Example of erroneous code:
 
 ```compile_fail,E0528
-#![feature(slice_patterns)]
-
 let r = &[1, 2];
 match r {
     &[a, b, c, rest @ ..] => { // error: pattern requires at least 3
@@ -19,8 +17,6 @@ Ensure that the matched array has at least as many elements as the pattern
 requires. You can match an arbitrary number of remaining elements with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4, 5];
 match r {
     &[a, b, c, rest @ ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md
index 803a2514865..bf1f72be325 100644
--- a/src/librustc_error_codes/error_codes/E0730.md
+++ b/src/librustc_error_codes/error_codes/E0730.md
@@ -18,8 +18,6 @@ Ensure that the pattern is consistent with the size of the matched
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs
index d880fc84b38..007cee4c764 100644
--- a/src/librustc_feature/accepted.rs
+++ b/src/librustc_feature/accepted.rs
@@ -257,6 +257,8 @@ declare_features! (
     /// Allows relaxing the coherence rules such that
     /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
     (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
+    /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
+    (accepted, slice_patterns, "1.42.0", Some(62254), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 4c8c47a5671..6af9b6c0872 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -262,9 +262,6 @@ declare_features! (
     /// Allows using non lexical lifetimes (RFC 2094).
     (active, nll, "1.0.0", Some(43234), None),
 
-    /// Allows using slice patterns.
-    (active, slice_patterns, "1.0.0", Some(62254), None),
-
     /// Allows the definition of `const` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(57563), None),
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 0fec4bff163..cf925ab9187 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -10,7 +10,7 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(rustc_private)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 1c25b269b18..5e42ba32790 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -7,7 +7,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
 #![feature(inner_deref)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
index 5a17f36e1da..42292d635bc 100644
--- a/src/librustc_mir_build/lib.rs
+++ b/src/librustc_mir_build/lib.rs
@@ -5,7 +5,7 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(bool_to_option)]
 #![recursion_limit = "256"]
 
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 9227e968ecc..08f4f210152 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -2,7 +2,7 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 use syntax::ast;
 use syntax::print::pprust;
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 65eb07b989d..d746f097928 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -7,7 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 17413e77f90..84c6d720b8e 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -11,7 +11,7 @@
 #![feature(box_syntax)]
 #![feature(bool_to_option)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[macro_use]
 extern crate log;
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
index 2548d2cff97..e5ec98743e0 100644
--- a/src/librustc_ty/lib.rs
+++ b/src/librustc_ty/lib.rs
@@ -8,7 +8,7 @@
 #![feature(bool_to_option)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index b951883ac19..95cd3c631ed 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -64,7 +64,7 @@ This API is completely unstable and subject to change.
 #![feature(exhaustive_patterns)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f90647472c6..c8fae91fcf3 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -294,7 +294,7 @@
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0184a3214b5..b0c2aa3dbb2 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -13,7 +13,7 @@
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(try_trait)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(unicode_internals)]
 #![recursion_limit = "256"]
 
diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs
index f2e1864096e..d587d237227 100644
--- a/src/test/mir-opt/uniform_array_move_out.rs
+++ b/src/test/mir-opt/uniform_array_move_out.rs
@@ -1,5 +1,4 @@
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn move_out_from_end() {
     let a = [box 1, box 2];
diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
index a0ef92743ac..34adb42a32f 100644
--- a/src/test/ui/match/match-vec-mismatch.rs
+++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     match "foo".to_string() {
         ['f', 'o', ..] => {}
diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
index a3523bb689e..c4548142c13 100644
--- a/src/test/ui/match/match-vec-mismatch.stderr
+++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
@@ -1,29 +1,29 @@
 error[E0425]: cannot find value `does_not_exist` in this scope
-  --> $DIR/match-vec-mismatch.rs:28:11
+  --> $DIR/slice-pat-type-mismatches.rs:26:11
    |
 LL |     match does_not_exist {
    |           ^^^^^^^^^^^^^^ not found in this scope
 
 error[E0529]: expected an array or slice, found `std::string::String`
-  --> $DIR/match-vec-mismatch.rs:5:9
+  --> $DIR/slice-pat-type-mismatches.rs:3:9
    |
 LL |         ['f', 'o', ..] => {}
    |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
 
 error[E0527]: pattern requires 1 element but array has 3
-  --> $DIR/match-vec-mismatch.rs:20:9
+  --> $DIR/slice-pat-type-mismatches.rs:18:9
    |
 LL |         [0] => {},
    |         ^^^ expected 3 elements
 
 error[E0528]: pattern requires at least 4 elements but array has 3
-  --> $DIR/match-vec-mismatch.rs:25:9
+  --> $DIR/slice-pat-type-mismatches.rs:23:9
    |
 LL |         [0, 1, 2, 3, x @ ..] => {}
    |         ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
 
 error[E0282]: type annotations needed
-  --> $DIR/match-vec-mismatch.rs:36:9
+  --> $DIR/slice-pat-type-mismatches.rs:34:9
    |
 LL |         [] => {}
    |         ^^ cannot infer type
diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
index 00f4374b256..97e33624bf6 100644
--- a/src/test/ui/parser/match-vec-invalid.rs
+++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
@@ -3,8 +3,6 @@ fn main() {
     match a {
         [1, tail @ .., tail @ ..] => {},
         //~^ ERROR identifier `tail` is bound more than once in the same pattern
-        //~| ERROR subslice patterns are unstable
-        //~| ERROR subslice patterns are unstable
         //~| ERROR `..` can only be used once per slice pattern
         _ => ()
     }
diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr
new file mode 100644
index 00000000000..4d6078788b2
--- /dev/null
+++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr
@@ -0,0 +1,24 @@
+error[E0416]: identifier `tail` is bound more than once in the same pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:24
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                        ^^^^ used in a pattern more than once
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:31
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                    --         ^^ can only be used once per slice pattern
+   |                    |
+   |                    previously used here
+
+error[E0308]: mismatched types
+  --> $DIR/subslice-only-once-semantic-restriction.rs:11:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected `()`, found integer
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0416.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
index 0e767d9613a..69c33921868 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
@@ -2,7 +2,7 @@
 
 // run-pass
 
-#![feature(slice_patterns, const_fn, const_if_match)]
+#![feature(const_fn, const_if_match)]
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
index 5444f8a9051..0b793fa0120 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
@@ -2,8 +2,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
diff --git a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
index 1ebf3def788..e05790911f5 100644
--- a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
+++ b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs
@@ -4,8 +4,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #![allow(unreachable_patterns)]
 
 use std::convert::identity;
diff --git a/src/test/ui/array-slice-vec/vec-matching-fixed.rs b/src/test/ui/array-slice-vec/vec-matching-fixed.rs
index 5253bc1b214..fdeb7e4fda6 100644
--- a/src/test/ui/array-slice-vec/vec-matching-fixed.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-fixed.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1, 2, 3];
     match x {
diff --git a/src/test/ui/array-slice-vec/vec-matching-fold.rs b/src/test/ui/array-slice-vec/vec-matching-fold.rs
index f416160db24..998899271e4 100644
--- a/src/test/ui/array-slice-vec/vec-matching-fold.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-fold.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 use std::fmt::Debug;
 
 fn foldl<T, U, F>(values: &[T],
diff --git a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
index f0602c328b0..ed34f074a92 100644
--- a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
+++ b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
@@ -1,7 +1,6 @@
 // run-pass
-#![allow(unused_variables)]
 
-#![feature(slice_patterns)]
+#![allow(unused_variables)]
 
 pub fn main() {
     let x = &[1, 2, 3, 4, 5];
diff --git a/src/test/ui/array-slice-vec/vec-matching.rs b/src/test/ui/array-slice-vec/vec-matching.rs
index 49c736bd728..7009244aa18 100644
--- a/src/test/ui/array-slice-vec/vec-matching.rs
+++ b/src/test/ui/array-slice-vec/vec-matching.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1];
     match x {
diff --git a/src/test/ui/array-slice-vec/vec-tail-matching.rs b/src/test/ui/array-slice-vec/vec-tail-matching.rs
index 3c7b160dcc5..5f1699227d8 100644
--- a/src/test/ui/array-slice-vec/vec-tail-matching.rs
+++ b/src/test/ui/array-slice-vec/vec-tail-matching.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 struct Foo {
     string: &'static str
 }
diff --git a/src/test/ui/binding/empty-types-in-patterns.rs b/src/test/ui/binding/empty-types-in-patterns.rs
index 4271ffb7b1b..0d0dbcaf40f 100644
--- a/src/test/ui/binding/empty-types-in-patterns.rs
+++ b/src/test/ui/binding/empty-types-in-patterns.rs
@@ -1,7 +1,8 @@
 // run-pass
+
 #![feature(never_type, never_type_fallback)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(unreachable_patterns)]
 #![allow(unreachable_code)]
 #![allow(unused_variables)]
diff --git a/src/test/ui/binding/irrefutable-slice-patterns.rs b/src/test/ui/binding/irrefutable-slice-patterns.rs
index ac733ef6e9c..048e1e5e9b4 100644
--- a/src/test/ui/binding/irrefutable-slice-patterns.rs
+++ b/src/test/ui/binding/irrefutable-slice-patterns.rs
@@ -1,7 +1,6 @@
 // run-pass
-// #47096
 
-#![feature(slice_patterns)]
+// Regression test for #47096.
 
 fn foo(s: &[i32]) -> &[i32] {
     let &[ref xs @ ..] = s;
diff --git a/src/test/ui/binding/match-byte-array-patterns.rs b/src/test/ui/binding/match-byte-array-patterns.rs
index e87745705da..f0c988c01c2 100644
--- a/src/test/ui/binding/match-byte-array-patterns.rs
+++ b/src/test/ui/binding/match-byte-array-patterns.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let buf = &[0u8; 4];
diff --git a/src/test/ui/binding/match-vec-alternatives.rs b/src/test/ui/binding/match-vec-alternatives.rs
index 9b06a86a7b9..af95eb95df0 100644
--- a/src/test/ui/binding/match-vec-alternatives.rs
+++ b/src/test/ui/binding/match-vec-alternatives.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
     match (l1, l2) {
diff --git a/src/test/ui/binding/zero_sized_subslice_match.rs b/src/test/ui/binding/zero_sized_subslice_match.rs
index 5326fa612a8..187c2983633 100644
--- a/src/test/ui/binding/zero_sized_subslice_match.rs
+++ b/src/test/ui/binding/zero_sized_subslice_match.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let x = [(), ()];
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
index a70ccb7aa4b..0229ca37a69 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -1,6 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
 #![allow(unused_variables)]
 
 // run-pass
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
index 984eb8804b7..32057d5c126 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
@@ -1,7 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
-
 fn arr_by_ref(mut x: [String; 3]) {
     let f = || {
         let [ref y, ref z @ ..] = x;
diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
index c5b27f5f8b4..483975e5778 100644
--- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
+++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:9:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:7:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -13,7 +13,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:18:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:16:13
    |
 LL |     let mut f = || {
    |                 -- mutable borrow occurs here
@@ -27,7 +27,7 @@ LL |     f();
    |     - mutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:27:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:25:5
    |
 LL | fn arr_by_move(x: [String; 3]) {
    |                - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait
@@ -40,7 +40,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:35:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:33:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -54,7 +54,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:44:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:42:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
@@ -68,7 +68,7 @@ LL |     f();
    |     - first borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:53:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:51:5
    |
 LL | fn arr_box_by_move(x: Box<[String; 3]>) {
    |                    - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait
@@ -81,7 +81,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:61:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:59:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -95,7 +95,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:70:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:68:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
index 8425960aa86..c8bfbe0729c 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs
@@ -1,7 +1,5 @@
 // ignore-tidy-linelength
 
-#![feature(slice_patterns)]
-
 pub struct Foo {
   x: u32
 }
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
index 4213523d2fa..075e0e2e451 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:258:13
+  --> $DIR/borrowck-describe-lvalue.rs:256:13
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
@@ -9,7 +9,7 @@ LL |             *y = 1;
    |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:268:20
+  --> $DIR/borrowck-describe-lvalue.rs:266:20
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
@@ -19,7 +19,7 @@ LL |                    *y = 1;
    |                    ------ first borrow later used here
 
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/borrowck-describe-lvalue.rs:266:16
+  --> $DIR/borrowck-describe-lvalue.rs:264:16
    |
 LL |              || {
    |               - inferred to be a `FnMut` closure
@@ -35,7 +35,7 @@ LL | |                 }
    = note: ...therefore, they cannot allow references to captured variables to escape
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:41:9
+  --> $DIR/borrowck-describe-lvalue.rs:39:9
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
@@ -45,7 +45,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:48:9
+  --> $DIR/borrowck-describe-lvalue.rs:46:9
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
@@ -55,7 +55,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:55:9
+  --> $DIR/borrowck-describe-lvalue.rs:53:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -65,7 +65,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:63:20
+  --> $DIR/borrowck-describe-lvalue.rs:61:20
    |
 LL |         let x = e.x();
    |                 - borrow of `e` occurs here
@@ -77,7 +77,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:71:9
+  --> $DIR/borrowck-describe-lvalue.rs:69:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -87,7 +87,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:78:9
+  --> $DIR/borrowck-describe-lvalue.rs:76:9
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
@@ -97,7 +97,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:85:9
+  --> $DIR/borrowck-describe-lvalue.rs:83:9
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
@@ -107,7 +107,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:92:9
+  --> $DIR/borrowck-describe-lvalue.rs:90:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -117,7 +117,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:100:20
+  --> $DIR/borrowck-describe-lvalue.rs:98:20
    |
 LL |         let x = e.x();
    |                 - borrow of `*e` occurs here
@@ -129,7 +129,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:109:9
+  --> $DIR/borrowck-describe-lvalue.rs:107:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -139,7 +139,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:117:15
+  --> $DIR/borrowck-describe-lvalue.rs:115:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -151,7 +151,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:122:18
+  --> $DIR/borrowck-describe-lvalue.rs:120:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -163,7 +163,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:127:25
+  --> $DIR/borrowck-describe-lvalue.rs:125:25
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -175,7 +175,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:132:28
+  --> $DIR/borrowck-describe-lvalue.rs:130:28
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -187,7 +187,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:143:15
+  --> $DIR/borrowck-describe-lvalue.rs:141:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -199,7 +199,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:148:18
+  --> $DIR/borrowck-describe-lvalue.rs:146:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -211,7 +211,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:153:15
+  --> $DIR/borrowck-describe-lvalue.rs:151:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -223,7 +223,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:158:18
+  --> $DIR/borrowck-describe-lvalue.rs:156:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -235,7 +235,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:171:13
+  --> $DIR/borrowck-describe-lvalue.rs:169:13
    |
 LL |         let x = &mut e;
    |                 ------ borrow of `e` occurs here
@@ -247,7 +247,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:171:18
+  --> $DIR/borrowck-describe-lvalue.rs:169:18
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -259,7 +259,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:175:23
+  --> $DIR/borrowck-describe-lvalue.rs:173:23
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -271,7 +271,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:188:22
+  --> $DIR/borrowck-describe-lvalue.rs:186:22
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -283,7 +283,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:194:28
+  --> $DIR/borrowck-describe-lvalue.rs:192:28
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -295,7 +295,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0503]: cannot use `*v` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -306,7 +306,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[_].y` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -317,7 +317,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:247:24
+  --> $DIR/borrowck-describe-lvalue.rs:245:24
    |
 LL |         let x = &mut v;
    |                 ------ mutable borrow occurs here
@@ -329,7 +329,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:210:29
+  --> $DIR/borrowck-describe-lvalue.rs:208:29
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -340,7 +340,7 @@ LL |             drop(x);
    |                  - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:225:33
+  --> $DIR/borrowck-describe-lvalue.rs:223:33
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -351,7 +351,7 @@ LL |             drop(x);
    |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/borrowck-describe-lvalue.rs:278:22
+  --> $DIR/borrowck-describe-lvalue.rs:276:22
    |
 LL |                 drop(x);
    |                      - value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
index 232d43679b4..c1513fcba8a 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
index e46a58a8a35..84930b000cc 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-match.rs:15:14
+  --> $DIR/borrowck-move-out-from-array-match.rs:13:14
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |         [.., _y] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-match.rs:25:14
+  --> $DIR/borrowck-move-out-from-array-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |         [.., _y] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:35:15
+  --> $DIR/borrowck-move-out-from-array-match.rs:33:15
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -32,7 +32,7 @@ LL |         [.., (_y, _)] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:46:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:57:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:55:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:68:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:79:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:91:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:89:11
    |
 LL |         [_y @ .., _, _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |         [(_x, _), _, _] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:101:15
+  --> $DIR/borrowck-move-out-from-array-match.rs:99:15
    |
 LL |         [_, _, _y @ ..] => {}
    |                ------- value moved here
@@ -98,7 +98,7 @@ LL |         [.., (_x, _)] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:112:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
    |          ------ value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
index e5e61697c68..056b8e672bd 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
@@ -3,8 +3,6 @@
 // Once the bug is fixed, the test, which is derived from a
 // passing test for `let` statements, should become check-pass.
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
index 72cd4207cce..ff5eab2442c 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:19:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:30:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:43:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -32,7 +32,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:54:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:65:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:76:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:87:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
    |             ------- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:98:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:111:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
    |          ------ value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
index 8f274cf73cb..c91b4286b64 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
index 1ca3df52ada..604a25cdcc1 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
index 028442a4c07..0ef63105cfb 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:15:14
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:13:14
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |         [.., ref _y] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:25:14
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |         [.., ref _y] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:35:15
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -32,7 +32,7 @@ LL |         [.., (ref _y, _)] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:46:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:57:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:68:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:79:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:91:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11
    |
 LL |         [_y @ .., _, _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |         [(ref _x, _), _, _] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:101:15
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15
    |
 LL |         [_, _, _y @ ..] => {}
    |                ------- value moved here
@@ -98,7 +98,7 @@ LL |         [.., (ref _x, _)] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:112:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
    |          ------ value moved here
@@ -109,7 +109,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:125:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -120,7 +120,7 @@ LL |     a[2] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:133:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -131,7 +131,7 @@ LL |     a[2].1 = Default::default();
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:141:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5
    |
 LL |         [_, _, _x @ ..] => {}
    |                ------- value moved here
@@ -142,7 +142,7 @@ LL |     a[0] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:149:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5
    |
 LL |         [_, _, _x @ ..] => {}
    |                ------- value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
index 79fe5930096..5afd6835dcf 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
@@ -3,8 +3,6 @@
 // Once the bug is fixed, the test, which is derived from a
 // passing test for `let` statements, should become check-pass.
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
index 43ba2b664a1..a4042ce7db3 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:19:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:30:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:43:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -32,7 +32,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:54:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:65:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:76:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:87:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
    |             ------- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:98:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:111:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
    |          ------ value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
index 57ce2417570..e3498cef377 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
index 778beefbf2c..ad08367a3b5 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
index 2a7b89132c1..7ad4116645e 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:12:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@ LL |     let [.., ref _y] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:18:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@ LL |     let [.., ref _y] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-use.rs:24:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@ LL |     let [.., (ref _y, _)] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:32:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@ LL |     let [ref _y @ .., _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:38:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@ LL |     let [_, _, ref _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:44:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@ LL |     let [ref _y @ .., _, _] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:50:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@ LL |     let [_, _, ref _y @ ..] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:56:11
+  --> $DIR/borrowck-move-out-from-array-use.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@ LL |     let [(ref _x, _), _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:62:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@ LL |     let [.., (ref _x, _)] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:70:13
+  --> $DIR/borrowck-move-out-from-array-use.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
@@ -99,7 +99,7 @@ LL |     let [_, ref _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:78:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:76:5
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -109,7 +109,7 @@ LL |     a[2] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:84:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:82:5
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -119,7 +119,7 @@ LL |     a[2].1 = Default::default();
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:90:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:88:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
@@ -129,7 +129,7 @@ LL |     a[0] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:96:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:94:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
index f9d3f6f2c07..83755812f4b 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
index 08134a2a323..b7babd93ed7 100644
--- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:12:14
+  --> $DIR/borrowck-move-out-from-array.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@ LL |     let [.., _y] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:18:14
+  --> $DIR/borrowck-move-out-from-array.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@ LL |     let [.., _y] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:24:15
+  --> $DIR/borrowck-move-out-from-array.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@ LL |     let [.., (_y, _)] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:32:10
+  --> $DIR/borrowck-move-out-from-array.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@ LL |     let [_y @ .., _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:38:16
+  --> $DIR/borrowck-move-out-from-array.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@ LL |     let [_, _, _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:44:10
+  --> $DIR/borrowck-move-out-from-array.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@ LL |     let [_y @ .., _, _] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:50:16
+  --> $DIR/borrowck-move-out-from-array.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@ LL |     let [_, _, _y @ ..] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:56:11
+  --> $DIR/borrowck-move-out-from-array.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@ LL |     let [(_x, _), _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:62:15
+  --> $DIR/borrowck-move-out-from-array.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@ LL |     let [.., (_x, _)] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:70:13
+  --> $DIR/borrowck-move-out-from-array.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
index fa9a3c217db..8ece81a3c84 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
@@ -1,7 +1,5 @@
 // Test that we do not permit moves from &[] matched by a vec pattern.
 
-#![feature(slice_patterns)]
-
 #[derive(Clone, Debug)]
 struct Foo {
     string: String
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
index 8fb4c062c03..a345c1238f0 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
-  --> $DIR/borrowck-move-out-of-vec-tail.rs:19:19
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:17:19
    |
 LL |             match tail {
    |                   ^^^^ cannot move out of here
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
index 7d91a212647..a8e56f648e2 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
index f03a2ab8fa8..6b210d73228 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
index e50e7eb3e22..0432aaf51d2 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:8:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:6:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@ LL |     nop(&[first, second, second2, third]);
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:14:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:12:14
    |
 LL |     let [.., ref fourth, ref third, _, ref first] = *s;
    |                          --------- immutable borrow occurs here
@@ -19,7 +19,7 @@ LL |     nop(&[first, third, third2, fourth]);
    |                  ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:16
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:19:16
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                 ------------- immutable borrow occurs here
@@ -30,7 +30,7 @@ LL |     nop(&[from_begin2, from_end1, from_end3, from_end4]);
    |                                              --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:23:19
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:19
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                                ------------- immutable borrow occurs here
@@ -41,7 +41,7 @@ LL |     nop(&[from_begin3, from_end1, from_end3, from_end4]);
    |                                   --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:28:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:26:14
    |
 LL |     let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
    |                                               --------------- immutable borrow occurs here
@@ -52,7 +52,7 @@ LL |     nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
    |                                     ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:34:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:32:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -62,7 +62,7 @@ LL |     nop(&[first, second]);
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:41:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:39:10
    |
 LL |     let [.., ref second, ref first] = *s;
    |              ---------- immutable borrow occurs here
@@ -72,7 +72,7 @@ LL |     nop(&[first, second]);
    |                  ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:48:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:46:10
    |
 LL |     let [_,  ref s1 @ ..] = *s;
    |              ----------- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
index 048813b2b93..4367596c6ea 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
@@ -1,7 +1,4 @@
 // run-pass
-//compile-flags: -Z borrowck=mir
-
-#![feature(slice_patterns)]
 
 fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
     match *v {
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
index e69071f8772..6390dc3a91a 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
index 2ef98741dc3..0e1c90a1cd8 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
index b6f5ac64b20..d3388e071aa 100644
--- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
+++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:8:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:6:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@ LL |             nop(&[first, second, second2, third]);
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:16:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:14:21
    |
 LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
    |                             --------- immutable borrow occurs here
@@ -19,7 +19,7 @@ LL |             nop(&[first, third, third2, fourth]);
    |                          ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:24:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:22:20
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                    ------------- immutable borrow occurs here
@@ -29,7 +29,7 @@ LL |             nop(&[from_begin1, from_end1, from_end3, from_end4]);
    |                                                      --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:27:23
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:25:23
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -40,7 +40,7 @@ LL |             nop(&[from_begin2, from_end1, from_end3, from_end4]);
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:30:26
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:28:26
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -51,7 +51,7 @@ LL |             nop(&[from_begin3, from_end1, from_end3, from_end4]);
    |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:35:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:33:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -61,7 +61,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:38:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:36:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -72,7 +72,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
    |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:41:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:39:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                              --------------- immutable borrow occurs here
@@ -83,7 +83,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
    |                                ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:49:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:47:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -93,7 +93,7 @@ LL |             nop(&[first, second]);
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:58:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:56:17
    |
 LL |     if let [.., ref second, ref first] = *s {
    |                 ---------- immutable borrow occurs here
@@ -103,7 +103,7 @@ LL |             nop(&[first, second]);
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:67:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:65:17
    |
 LL |     if let [_, _, _, ref s1 @ ..] = *s {
    |                      ----------- immutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
index 53a9bcef74a..cd853b83363 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
index da6d9293b40..170982b1693 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -8,7 +8,7 @@ LL |     tail
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:20:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:18:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -17,7 +17,7 @@ LL |     init
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:30:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:28:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
index dd9023f6d9f..05859c95d17 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a() {
     let mut v = vec![1, 2, 3];
     let vb: &mut [isize] = &mut v;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
index 251f4459290..5141fcc1bb2 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `v` as mutable more than once at a time
-  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13
+  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:6:13
    |
 LL |     let vb: &mut [isize] = &mut v;
    |                            ------ first mutable borrow occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
index 420223009a4..9b8ba2ea8ad 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
@@ -1,7 +1,3 @@
-// http://rust-lang.org/COPYRIGHT.
-
-#![feature(slice_patterns)]
-
 fn main() {
     let mut a = [1, 2, 3, 4];
     let t = match a {
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
index 9f8e6fe3b68..ff70ba9fcca 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `a[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:8:5
    |
 LL |         [1, 2, ref tail @ ..] => tail,
    |                ------------- borrow of `a[_]` occurs here
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
index e274d105e05..67b6c12ba80 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -1,6 +1,5 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn a() {
     let mut vec = [box 1, box 2, box 3];
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index a3324f25d0b..e2c0852dd83 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:10:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:9:13
    |
 LL |         [box ref _a, _, _] => {
    |              ------ borrow of `vec[_]` occurs here
@@ -11,7 +11,7 @@ LL |             _a.use_ref();
    |             -- borrow later used here
 
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
    |
 LL |         &mut [ref _b @ ..] => {
    |               ----------- borrow of `vec[_]` occurs here
@@ -23,7 +23,7 @@ LL |             _b.use_ref();
    |             -- borrow later used here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:35:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -45,7 +45,7 @@ LL |         ] => {
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:47:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -55,7 +55,7 @@ LL |     let a = vec[0];
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:56:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -74,7 +74,7 @@ LL |          _b] => {}
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:66:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -84,7 +84,7 @@ LL |     let a = vec[0];
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:75:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -100,7 +100,7 @@ LL |         &mut [_a, _b, _c] => {}
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:86:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
index c35be2f6be6..39872825cd2 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a isize {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
index c1290a6f63f..7e21c55f21b 100644
--- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
diff --git a/src/test/ui/consts/const_prop_slice_pat_ice.rs b/src/test/ui/consts/const_prop_slice_pat_ice.rs
index 5fec36e44bd..60b06a497d6 100644
--- a/src/test/ui/consts/const_prop_slice_pat_ice.rs
+++ b/src/test/ui/consts/const_prop_slice_pat_ice.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     match &[0, 1] as &[i32] {
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 91063edf0f6..30a89605944 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -7,7 +7,6 @@
 // edition:2018
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(slice_patterns)]
 #![allow(unused)]
 
 use std::{
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index 0f0ec0ba460..b4406204a5d 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -1,11 +1,10 @@
 // run-pass
-#![allow(unused_assignments)]
-#![allow(unused_variables)]
-
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions)]
-#![feature(slice_patterns)]
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 
 use std::cell::{Cell, RefCell};
 use std::mem::ManuallyDrop;
diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs
index 17d03b14fc6..0a337c9611c 100644
--- a/src/test/ui/error-codes/E0528.rs
+++ b/src/test/ui/error-codes/E0528.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let r = &[1, 2];
     match r {
diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr
index 0f566091145..21615f954c3 100644
--- a/src/test/ui/error-codes/E0528.stderr
+++ b/src/test/ui/error-codes/E0528.stderr
@@ -1,5 +1,5 @@
 error[E0528]: pattern requires at least 3 elements but array has 2
-  --> $DIR/E0528.rs:6:10
+  --> $DIR/E0528.rs:4:10
    |
 LL |         &[a, b, c, rest @ ..] => {
    |          ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
deleted file mode 100644
index f2a1b135b69..00000000000
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
-
-fn main() {
-    let x = [1, 2, 3, 4, 5];
-    match x {
-        [1, 2, ..] => {} //~ ERROR subslice patterns are unstable
-        [1, .., 5] => {} //~ ERROR subslice patterns are unstable
-        [.., 4, 5] => {} //~ ERROR subslice patterns are unstable
-    }
-
-    let x = [ 1, 2, 3, 4, 5 ];
-    match x {
-        [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable
-    }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
deleted file mode 100644
index d4946a42b8f..00000000000
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
+++ /dev/null
@@ -1,57 +0,0 @@
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:6:16
-   |
-LL |         [1, 2, ..] => {}
-   |                ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:7:13
-   |
-LL |         [1, .., 5] => {}
-   |             ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:8:10
-   |
-LL |         [.., 4, 5] => {}
-   |          ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:13:11
-   |
-LL |         [ xs @ .., 4, 5 ] => {}
-   |           ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:14:14
-   |
-LL |         [ 1, xs @ .., 5 ] => {}
-   |              ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:15:17
-   |
-LL |         [ 1, 2, xs @ .. ] => {}
-   |                 ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/ignore-all-the-things.rs b/src/test/ui/ignore-all-the-things.rs
index 8c046a289fa..5980e1a857f 100644
--- a/src/test/ui/ignore-all-the-things.rs
+++ b/src/test/ui/ignore-all-the-things.rs
@@ -3,9 +3,6 @@
 #![allow(non_shorthand_field_patterns)]
 #![allow(dead_code)]
 #![allow(unused_variables)]
-// pretty-expanded FIXME #23616
-
-#![feature(slice_patterns)]
 
 struct Foo(isize, isize, isize, isize);
 struct Bar{a: isize, b: isize, c: isize, d: isize}
diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs
index 08661318074..0481c1fd9e1 100644
--- a/src/test/ui/issues/issue-12369.rs
+++ b/src/test/ui/issues/issue-12369.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr
index f27425e28c6..754b94bab75 100644
--- a/src/test/ui/issues/issue-12369.stderr
+++ b/src/test/ui/issues/issue-12369.stderr
@@ -1,11 +1,11 @@
 error: unreachable pattern
-  --> $DIR/issue-12369.rs:10:9
+  --> $DIR/issue-12369.rs:9:9
    |
 LL |         &[10,a, ref rest @ ..] => 10
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-12369.rs:2:9
+  --> $DIR/issue-12369.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-12567.rs b/src/test/ui/issues/issue-12567.rs
index 643d9a2fc69..1b2a37de475 100644
--- a/src/test/ui/issues/issue-12567.rs
+++ b/src/test/ui/issues/issue-12567.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
     match (l1, l2) {
     //~^ ERROR: cannot move out of type `[T]`, a non-copy slice
diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr
index 9d9a88f4f9b..2a88d8f0524 100644
--- a/src/test/ui/issues/issue-12567.stderr
+++ b/src/test/ui/issues/issue-12567.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
@@ -13,7 +13,7 @@ LL |         (&[hd1, ..], &[hd2, ..])
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs
index b11b1cda38a..4dd6981d448 100644
--- a/src/test/ui/issues/issue-15080.rs
+++ b/src/test/ui/issues/issue-15080.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let mut x: &[_] = &[1, 2, 3, 4];
diff --git a/src/test/ui/issues/issue-15104.rs b/src/test/ui/issues/issue-15104.rs
index ee977541137..47b207ea9cb 100644
--- a/src/test/ui/issues/issue-15104.rs
+++ b/src/test/ui/issues/issue-15104.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(count_members(&[1, 2, 3, 4]), 4);
diff --git a/src/test/ui/issues/issue-17877.rs b/src/test/ui/issues/issue-17877.rs
index fefa3f2f873..126e01de5ee 100644
--- a/src/test/ui/issues/issue-17877.rs
+++ b/src/test/ui/issues/issue-17877.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(match [0u8; 1024] {
diff --git a/src/test/ui/issues/issue-23311.rs b/src/test/ui/issues/issue-23311.rs
index f275c6338b1..62c96840b3b 100644
--- a/src/test/ui/issues/issue-23311.rs
+++ b/src/test/ui/issues/issue-23311.rs
@@ -1,7 +1,6 @@
 // run-pass
-// Test that we do not ICE when pattern matching an array against a slice.
 
-#![feature(slice_patterns)]
+// Test that we do not ICE when pattern matching an array against a slice.
 
 fn main() {
     match "foo".as_bytes() {
diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs
index 00e09f3f077..b9d34b0555a 100644
--- a/src/test/ui/issues/issue-26619.rs
+++ b/src/test/ui/issues/issue-26619.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub struct History<'a> { pub _s: &'a str }
 
 impl<'a> History<'a> {
diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr
index d1157cda92b..1282fd7d3c2 100644
--- a/src/test/ui/issues/issue-26619.stderr
+++ b/src/test/ui/issues/issue-26619.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing function parameter
-  --> $DIR/issue-26619.rs:7:76
+  --> $DIR/issue-26619.rs:5:76
    |
 LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
    |                                                                  --------  ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs
index 31b3aba6bc2..458e999c3fa 100644
--- a/src/test/ui/issues/issue-37598.rs
+++ b/src/test/ui/issues/issue-37598.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn check(list: &[u8]) {
     match list {
diff --git a/src/test/ui/issues/issue-7784.rs b/src/test/ui/issues/issue-7784.rs
index 5b70bd6e5ff..b7323f09daf 100644
--- a/src/test/ui/issues/issue-7784.rs
+++ b/src/test/ui/issues/issue-7784.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 use std::ops::Add;
 
diff --git a/src/test/ui/moves/move-out-of-array-ref.rs b/src/test/ui/moves/move-out-of-array-ref.rs
index 4ca60ddfec2..343f00ff291 100644
--- a/src/test/ui/moves/move-out-of-array-ref.rs
+++ b/src/test/ui/moves/move-out-of-array-ref.rs
@@ -1,7 +1,5 @@
 // Ensure that we cannot move out of a reference to a fixed-size array
 
-#![feature(slice_patterns)]
-
 struct D { _x: u8 }
 
 impl Drop for D { fn drop(&mut self) { } }
diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr
index ae3d2f5f282..fd682e56ae1 100644
--- a/src/test/ui/moves/move-out-of-array-ref.stderr
+++ b/src/test/ui/moves/move-out-of-array-ref.stderr
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:10:24
+  --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -10,7 +10,7 @@ LL |     let [_, e, _, _] = *a;
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:15:27
+  --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
@@ -21,7 +21,7 @@ LL |     let [_, s @ .. , _] = *a;
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:20:24
+  --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -32,7 +32,7 @@ LL |     let [_, e, _, _] = *a;
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:25:27
+  --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
index d7c191bb5a2..8b0be2e7a66 100644
--- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/or-patterns/exhaustiveness-pass.rs b/src/test/ui/or-patterns/exhaustiveness-pass.rs
index ce0fe6fc2a3..f0dc3447f31 100644
--- a/src/test/ui/or-patterns/exhaustiveness-pass.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-pass.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index 860c7a1bde5..81bc1176f57 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr
deleted file mode 100644
index 58343e86d7b..00000000000
--- a/src/test/ui/parser/match-vec-invalid.stderr
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0416]: identifier `tail` is bound more than once in the same pattern
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^ used in a pattern more than once
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:13
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |             ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: `..` can only be used once per slice pattern
-  --> $DIR/match-vec-invalid.rs:4:31
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                    --         ^^ can only be used once per slice pattern
-   |                    |
-   |                    previously used here
-
-error[E0308]: mismatched types
-  --> $DIR/match-vec-invalid.rs:13:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0308, E0416, E0658.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs
index f27caa5d78c..7becffa9fe2 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.rs
+++ b/src/test/ui/parser/pat-lt-bracket-6.rs
@@ -4,7 +4,6 @@ fn main() {
 
     let Test(&desc[..]) = x;
     //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
-    //~^^ ERROR subslice patterns are unstable
 }
 
 const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr
index fe9603cb57f..035d0dbfe06 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.stderr
+++ b/src/test/ui/parser/pat-lt-bracket-6.stderr
@@ -7,22 +7,12 @@ LL |     let Test(&desc[..]) = x;
    |                   expected one of `)`, `,`, `@`, or `|`
    |                   help: missing `,`
 
-error[E0658]: subslice patterns are unstable
-  --> $DIR/pat-lt-bracket-6.rs:5:20
-   |
-LL |     let Test(&desc[..]) = x;
-   |                    ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
 error[E0308]: mismatched types
-  --> $DIR/pat-lt-bracket-6.rs:10:30
+  --> $DIR/pat-lt-bracket-6.rs:9:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected `()`, found integer
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
index 1d9f341c514..2cd375da9a5 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
@@ -1,7 +1,6 @@
 // Test that moving on both sides of an `@` pattern is not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
index f3f8fd655ce..12ebcb72af1 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
@@ -1,53 +1,53 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:12:9
+  --> $DIR/borrowck-move-and-move.rs:11:9
    |
 LL |     let a @ b = U;
    |         ^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:16:9
+  --> $DIR/borrowck-move-and-move.rs:15:9
    |
 LL |     let a @ (b, c) = (U, U);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:20:9
+  --> $DIR/borrowck-move-and-move.rs:19:9
    |
 LL |     let a @ (b, c) = (u(), u());
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:9
+  --> $DIR/borrowck-move-and-move.rs:24:9
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:21
+  --> $DIR/borrowck-move-and-move.rs:24:21
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:37:9
+  --> $DIR/borrowck-move-and-move.rs:36:9
    |
 LL |         xs @ [a, .., b] => {}
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:43:9
+  --> $DIR/borrowck-move-and-move.rs:42:9
    |
 LL |         xs @ [_, ys @ .., _] => {}
    |         ^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:32:12
+  --> $DIR/borrowck-move-and-move.rs:31:12
    |
 LL |     fn fun(a @ b: U) {}
    |            ^^^^^ binds an already bound by-move value by moving it
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:12:13
+  --> $DIR/borrowck-move-and-move.rs:11:13
    |
 LL |     let a @ b = U;
    |         ----^   - move occurs because value has type `main::U`, which does not implement the `Copy` trait
@@ -56,7 +56,7 @@ LL |     let a @ b = U;
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:16:17
+  --> $DIR/borrowck-move-and-move.rs:15:17
    |
 LL |     let a @ (b, c) = (U, U);
    |         --------^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -65,7 +65,7 @@ LL |     let a @ (b, c) = (U, U);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:20:17
+  --> $DIR/borrowck-move-and-move.rs:19:17
    |
 LL |     let a @ (b, c) = (u(), u());
    |         --------^-   ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -74,7 +74,7 @@ LL |     let a @ (b, c) = (u(), u());
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:16
+  --> $DIR/borrowck-move-and-move.rs:24:16
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -85,7 +85,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:29
+  --> $DIR/borrowck-move-and-move.rs:24:29
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -96,7 +96,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:37:22
+  --> $DIR/borrowck-move-and-move.rs:36:22
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -107,7 +107,7 @@ LL |         xs @ [a, .., b] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:43:18
+  --> $DIR/borrowck-move-and-move.rs:42:18
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -118,7 +118,7 @@ LL |         xs @ [_, ys @ .., _] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:32:16
+  --> $DIR/borrowck-move-and-move.rs:31:16
    |
 LL |     fn fun(a @ b: U) {}
    |            ----^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index afac8d990b4..092bd1133dd 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -4,7 +4,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
index fce31409e16..3b2f598dc01 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
@@ -2,7 +2,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 5772fadd1e7..e96c15b0fa7 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -1,23 +1,23 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:17:9
+  --> $DIR/borrowck-pat-at-and-box.rs:16:9
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:21:9
+  --> $DIR/borrowck-pat-at-and-box.rs:20:9
    |
 LL |     let a @ box b = Box::new(C);
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:33:25
+  --> $DIR/borrowck-pat-at-and-box.rs:32:25
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |                         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:37:21
+  --> $DIR/borrowck-pat-at-and-box.rs:36:21
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         ------------^
@@ -26,7 +26,7 @@ LL |     let ref a @ box b = Box::new(NC);
    |         by-ref pattern here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
    |         -----^^^^^^^---------
@@ -35,7 +35,7 @@ LL |     let ref a @ box ref mut b = Box::new(nc());
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:41:9
+  --> $DIR/borrowck-pat-at-and-box.rs:40:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -44,7 +44,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -53,7 +53,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:9
+  --> $DIR/borrowck-pat-at-and-box.rs:45:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -62,7 +62,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:9
+  --> $DIR/borrowck-pat-at-and-box.rs:51:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ---------^^^^^^^-----
@@ -71,7 +71,7 @@ LL |     let ref mut a @ box ref b = Box::new(NC);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:9
+  --> $DIR/borrowck-pat-at-and-box.rs:65:9
    |
 LL |         ref mut a @ box ref b => {
    |         ---------^^^^^^^-----
@@ -80,7 +80,7 @@ LL |         ref mut a @ box ref b => {
    |         mutable borrow occurs here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:75:38
+  --> $DIR/borrowck-pat-at-and-box.rs:74:38
    |
 LL |         box [Ok(a), ref xs @ .., Err(b)] => {}
    |                     -----------      ^ by-move pattern here
@@ -88,7 +88,7 @@ LL |         box [Ok(a), ref xs @ .., Err(b)] => {}
    |                     by-ref pattern here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:81:46
+  --> $DIR/borrowck-pat-at-and-box.rs:80:46
    |
 LL |         [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {}
    |                 -----   -----------          ^           --------- by-ref pattern here
@@ -98,19 +98,19 @@ LL |         [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {}
    |                 by-ref pattern here
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:25:11
+  --> $DIR/borrowck-pat-at-and-box.rs:24:11
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:29:11
+  --> $DIR/borrowck-pat-at-and-box.rs:28:11
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:11
+  --> $DIR/borrowck-pat-at-and-box.rs:57:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ---------^^^^^^^-----
@@ -119,7 +119,7 @@ LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           mutable borrow occurs here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:17:18
+  --> $DIR/borrowck-pat-at-and-box.rs:16:18
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ---------^   ------------ move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
@@ -128,7 +128,7 @@ LL |     let a @ box &b = Box::new(&C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:21:17
+  --> $DIR/borrowck-pat-at-and-box.rs:20:17
    |
 LL |     let a @ box b = Box::new(C);
    |         --------^   ----------- move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
@@ -137,7 +137,7 @@ LL |     let a @ box b = Box::new(C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:33:33
+  --> $DIR/borrowck-pat-at-and-box.rs:32:33
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |           -----------   --------^
@@ -147,7 +147,7 @@ LL |     match Box::new(C) { a @ box b => {} }
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:21
+  --> $DIR/borrowck-pat-at-and-box.rs:45:21
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ------------^^^^^^^^^
@@ -159,7 +159,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:25
+  --> $DIR/borrowck-pat-at-and-box.rs:51:25
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ----------------^^^^^
@@ -171,7 +171,7 @@ LL |     *a = Box::new(NC);
    |     -- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:25
+  --> $DIR/borrowck-pat-at-and-box.rs:65:25
    |
 LL |         ref mut a @ box ref b => {
    |         ----------------^^^^^
@@ -183,7 +183,7 @@ LL |             *a = Box::new(NC);
    |             -- mutable borrow later used here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:25:20
+  --> $DIR/borrowck-pat-at-and-box.rs:24:20
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ---------^
@@ -193,7 +193,7 @@ LL |     fn f1(a @ box &b: Box<&C>) {}
    |           move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:29:19
+  --> $DIR/borrowck-pat-at-and-box.rs:28:19
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           --------^
@@ -203,7 +203,7 @@ LL |     fn f2(a @ box b: Box<C>) {}
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:27
+  --> $DIR/borrowck-pat-at-and-box.rs:57:27
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ----------------^^^^^
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
index be19e5f2a85..c4ce50c8b9a 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
@@ -2,7 +2,6 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![feature(slice_patterns)]
 #![feature(bindings_after_at)]
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
index edf9fb31458..fb243016a11 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
@@ -4,7 +4,6 @@
 // of an `@` pattern according to NLL borrowck.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
index 559925c282f..e8510dfa649 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
@@ -1,5 +1,4 @@
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 enum Option<T> {
     None,
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index b5c26a1fa03..0d7b703f181 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow `z` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ---------^^^^^^^^^^^^^-----^
@@ -8,7 +8,7 @@ LL |         ref mut z @ &mut Some(ref a) => {
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         ---------^^^^-----------------^
@@ -18,7 +18,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         first mutable borrow occurs here
 
 error: cannot borrow `b` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      -----^^^---------
@@ -27,7 +27,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:36:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -36,7 +36,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -45,7 +45,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -55,7 +55,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -65,7 +65,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ---------^^^-----
@@ -74,7 +74,7 @@ LL |     let ref mut a @ ref b = u();
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:9
    |
 LL |     let ref a @ ref mut b = u();
    |         -----^^^---------
@@ -83,7 +83,7 @@ LL |     let ref a @ ref mut b = u();
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:56:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:55:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -92,7 +92,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:60:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -101,7 +101,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         ---------^^^^^^-----^
@@ -110,7 +110,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 ---------^^^^^^^-----^
@@ -119,7 +119,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----^^^^^^---------^
@@ -128,7 +128,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 -----^^^^^^^---------^
@@ -137,7 +137,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |         -----^^^^^^---------^
@@ -146,7 +146,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                 -----^^^^^^^---------^
@@ -155,7 +155,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |         ---------^^^^^^-----^
@@ -164,7 +164,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -173,7 +173,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |         -----^^^^^^---------^
@@ -182,7 +182,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                 -----^^^^^^^---------^
@@ -191,7 +191,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ---------^^^^^^-----^
@@ -200,7 +200,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -209,7 +209,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:116:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:115:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:132:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -249,7 +249,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
    |           -----^^^---------
@@ -258,7 +258,7 @@ LL |     fn f1(ref a @ ref mut b: U) {}
    |           immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
    |           ---------^^^-----
@@ -267,7 +267,7 @@ LL |     fn f2(ref mut a @ ref b: U) {}
    |           mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           -----^^^^^^^^^^^----------------^^^^^^^^
@@ -276,7 +276,7 @@ LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           immutable borrow occurs here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ----------------------^^^^^-
@@ -288,7 +288,7 @@ LL |             **z = None;
    |             ---------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:21
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:21
    |
 LL |     let ref mut a @ ref b = u();
    |         ------------^^^^^
@@ -300,7 +300,7 @@ LL |     *a = u();
    |     -------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:17
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:17
    |
 LL |     let ref a @ ref mut b = u();
    |         --------^^^^^^^^^
@@ -312,7 +312,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:20
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:20
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----------^^^^^^^^^-
@@ -324,7 +324,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:45
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:45
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 ------------^^^^^^^^^-
@@ -336,7 +336,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:61
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                                             ^^^^^^ cannot assign
@@ -344,7 +344,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
@@ -352,7 +352,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
@@ -360,7 +360,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
@@ -368,7 +368,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -376,7 +376,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -384,7 +384,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -396,7 +396,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -408,7 +408,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -420,7 +420,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
index 6b8b7545e68..f425b35630d 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
@@ -1,7 +1,6 @@
 // Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U;
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 1b5e6c74117..d07ad140cc2 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -1,5 +1,5 @@
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -8,7 +8,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -17,7 +17,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -26,7 +26,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -35,7 +35,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -44,7 +44,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:43:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -66,7 +66,7 @@ LL | |     ) = (U, [U, U, U]);
    | |_____^
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:52:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -88,31 +88,31 @@ LL | |         ) = (u(), [u(), u(), u()]);
    | |_________^
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -121,7 +121,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -130,7 +130,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -139,7 +139,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -148,7 +148,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -157,7 +157,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -166,7 +166,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -175,7 +175,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -184,7 +184,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -193,7 +193,7 @@ LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -202,7 +202,7 @@ LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
    |
 LL |           ref mut a @ [
    |           ^--------
@@ -220,7 +220,7 @@ LL | |         ] : [[U; 4]; 5]
    | |_________^
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -232,7 +232,7 @@ LL |     drop(a);
    |          - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -244,7 +244,7 @@ LL |     *a = U;
    |     ------ first borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:25
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:25
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ----------------^^^^^^^^^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -253,7 +253,7 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:21
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ------------^--   -------- move occurs because value has type `&mut (main::U, [main::U; 2])`, which does not implement the `Copy` trait
@@ -262,7 +262,7 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:18
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:18
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ---------^^^^^^^^^   ------ move occurs because value has type `&mut main::U`, which does not implement the `Copy` trait
@@ -271,7 +271,7 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:30
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:30
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ---------------------^^^^^^^^^-   ----------- move occurs because value has type `&mut (main::U, main::U)`, which does not implement the `Copy` trait
@@ -280,7 +280,7 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         value moved here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -292,7 +292,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -304,7 +304,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -316,7 +316,7 @@ LL |             drop(a);
    |                  - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
index c910cded96b..5b0482de220 100644
--- a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs
+++ b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
@@ -1,8 +1,6 @@
 // check-pass
 
-// This used to cause a stack overflow in the compiler.
-
-#![feature(slice_patterns)]
+// This used to cause a stack overflow during exhaustiveness checking in the compiler.
 
 fn main() {
     const LARGE_SIZE: usize = 1024 * 1024;
diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
index 6c54c938bf1..54dfa889ee3 100644
--- a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
+++ b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(slice_patterns)]
+
 #![deny(unreachable_patterns)]
 
 const C0: &'static [u8] = b"\x00";
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
index 7541ea3e2e2..9b6c8bd5556 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
index b28646b50cf..09484692fab 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
@@ -1,53 +1,53 @@
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:9:9
+  --> $DIR/match-byte-array-patterns.rs:8:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-byte-array-patterns.rs:2:9
+  --> $DIR/match-byte-array-patterns.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:15:9
+  --> $DIR/match-byte-array-patterns.rs:14:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:21:9
+  --> $DIR/match-byte-array-patterns.rs:20:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:27:9
+  --> $DIR/match-byte-array-patterns.rs:26:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:35:9
+  --> $DIR/match-byte-array-patterns.rs:34:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:41:9
+  --> $DIR/match-byte-array-patterns.rs:40:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:47:9
+  --> $DIR/match-byte-array-patterns.rs:46:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:53:9
+  --> $DIR/match-byte-array-patterns.rs:52:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.rs b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
index af7fd53a1f1..92d74b8c229 100644
--- a/src/test/ui/pattern/usefulness/match-slice-patterns.rs
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn check(list: &[Option<()>]) {
     match list {
     //~^ ERROR `&[_, Some(_), .., None, _]` not covered
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
index 72ae5d5fe3b..977a1128081 100644
--- a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
-  --> $DIR/match-slice-patterns.rs:4:11
+  --> $DIR/match-slice-patterns.rs:2:11
    |
 LL |     match list {
    |           ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
index 78810525bad..3342389be6e 100644
--- a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
index 415c24ae77e..e9a751074c2 100644
--- a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
@@ -1,23 +1,23 @@
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:9:9
+  --> $DIR/match-vec-unreachable.rs:8:9
    |
 LL |         [(1, 2), (2, 3), b] => (),
    |         ^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-vec-unreachable.rs:2:9
+  --> $DIR/match-vec-unreachable.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:19:9
+  --> $DIR/match-vec-unreachable.rs:18:9
    |
 LL |         [_, _, _, _, _] => { }
    |         ^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:27:9
+  --> $DIR/match-vec-unreachable.rs:26:9
    |
 LL |         ['a', 'b', 'c'] => {}
    |         ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
index 9423a2891a6..d198144790b 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 enum T { A(U), B }
 enum U { C, D }
 
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
index 67c818e19cb..72b4b522198 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:7:11
+  --> $DIR/non-exhaustive-match-nested.rs:5:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
@@ -7,7 +7,7 @@ LL |     match (l1, l2) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `A(C)` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:17:11
+  --> $DIR/non-exhaustive-match-nested.rs:15:11
    |
 LL | enum T { A(U), B }
    | ------------------
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
index bfca5352353..9947989dc12 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![allow(illegal_floating_point_literal_pattern)]
 
 enum T { A, B }
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
index 577867e4e71..a06ad578851 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `A` not covered
-  --> $DIR/non-exhaustive-match.rs:8:11
+  --> $DIR/non-exhaustive-match.rs:7:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -13,7 +13,7 @@ LL |     match x { T::B => { } }
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `false` not covered
-  --> $DIR/non-exhaustive-match.rs:9:11
+  --> $DIR/non-exhaustive-match.rs:8:11
    |
 LL |     match true {
    |           ^^^^ pattern `false` not covered
@@ -21,7 +21,7 @@ LL |     match true {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/non-exhaustive-match.rs:12:11
+  --> $DIR/non-exhaustive-match.rs:11:11
    |
 LL |     match Some(10) {
    |           ^^^^^^^^ pattern `Some(_)` not covered
@@ -29,7 +29,7 @@ LL |     match Some(10) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
-  --> $DIR/non-exhaustive-match.rs:15:11
+  --> $DIR/non-exhaustive-match.rs:14:11
    |
 LL |     match (2, 3, 4) {
    |           ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
@@ -37,7 +37,7 @@ LL |     match (2, 3, 4) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(A, A)` not covered
-  --> $DIR/non-exhaustive-match.rs:19:11
+  --> $DIR/non-exhaustive-match.rs:18:11
    |
 LL |     match (T::A, T::A) {
    |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
@@ -45,7 +45,7 @@ LL |     match (T::A, T::A) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `B` not covered
-  --> $DIR/non-exhaustive-match.rs:23:11
+  --> $DIR/non-exhaustive-match.rs:22:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -59,7 +59,7 @@ LL |     match T::A {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/non-exhaustive-match.rs:34:11
+  --> $DIR/non-exhaustive-match.rs:33:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[]` not covered
@@ -67,7 +67,7 @@ LL |     match *vec {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
-  --> $DIR/non-exhaustive-match.rs:47:11
+  --> $DIR/non-exhaustive-match.rs:46:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[_, _, _, _, ..]` not covered
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
index 4ca1cbcebcc..abb4ea8daf5 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 struct Foo {
     first: bool,
     second: Option<[usize; 4]>
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
index a0b497dd4c0..2a9fa07d22f 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:9:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:7:11
    |
 LL | / struct Foo {
 LL | |     first: bool,
@@ -13,7 +13,7 @@ LL |       match (Foo { first: true, second: None }) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:25:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:23:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -29,7 +29,7 @@ LL |       match Color::Red {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:37:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:35:11
    |
 LL | / enum Direction {
 LL | |     North, East, South, West
@@ -46,7 +46,7 @@ LL |       match Direction::North {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:46:11
    |
 LL | / enum ExcessiveEnum {
 LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
@@ -59,7 +59,7 @@ LL |       match ExcessiveEnum::First {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:56:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:54:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -75,7 +75,7 @@ LL |       match Color::Red {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:72:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:70:11
    |
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
@@ -83,7 +83,7 @@ LL |     match *x {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:85:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:83:11
    |
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
index 41ba2cc4501..52d1320dad1 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let s: &[bool] = &[true; 0];
     let s1: &[bool; 1] = &[false; 1];
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
index 8cb342f33df..b3701efef3d 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:10:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:8:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, _]` not covered
@@ -7,7 +7,7 @@ LL |     match s2 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:14:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:12:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, ..]` not covered
@@ -15,7 +15,7 @@ LL |     match s3 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:18:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:16:11
    |
 LL |     match s10 {
    |           ^^^ pattern `&[false, ..]` not covered
@@ -23,7 +23,7 @@ LL |     match s10 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:27:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:25:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, true]` not covered
@@ -31,7 +31,7 @@ LL |     match s2 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:32:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:30:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, .., true]` not covered
@@ -39,7 +39,7 @@ LL |     match s3 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:37:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:35:11
    |
 LL |     match s {
    |           ^ pattern `&[false, .., true]` not covered
@@ -47,7 +47,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:44:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:42:11
    |
 LL |     match s {
    |           ^ pattern `&[_, ..]` not covered
@@ -55,7 +55,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:48:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:46:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, ..]` not covered
@@ -63,7 +63,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:53:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:51:11
    |
 LL |     match s {
    |           ^ pattern `&[false, ..]` not covered
@@ -71,7 +71,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:58:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:56:11
    |
 LL |     match s {
    |           ^ pattern `&[false, _, ..]` not covered
@@ -79,7 +79,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:64:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:62:11
    |
 LL |     match s {
    |           ^ pattern `&[_, .., false]` not covered
@@ -87,7 +87,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:71:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:69:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, .., true]` not covered
@@ -95,7 +95,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:78:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:76:11
    |
 LL |     match s {
    |           ^ pattern `&[true, _, .., _]` not covered
@@ -103,7 +103,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:87:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:85:11
    |
 LL |     match s {
    |           ^ pattern `&[..]` not covered
@@ -111,7 +111,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:91:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:89:11
    |
 LL |     match s {
    |           ^ pattern `&[true]` not covered
@@ -119,7 +119,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:99:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:97:11
    |
 LL |     match s1 {
    |           ^^ pattern `&[false]` not covered
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
index 3b716bae772..cbf64e2c53d 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let s: &[bool] = &[true; 0];
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
index cd229a0fcbe..7c747b5e0b9 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
index 333ce170283..e24d1028117 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
+++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
@@ -1,41 +1,41 @@
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:9:9
+  --> $DIR/slice-patterns-reachability.rs:8:9
    |
 LL |         [true, ..] => {}
    |         ^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/slice-patterns-reachability.rs:2:9
+  --> $DIR/slice-patterns-reachability.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:10:9
+  --> $DIR/slice-patterns-reachability.rs:9:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:15:9
+  --> $DIR/slice-patterns-reachability.rs:14:9
    |
 LL |         [.., true] => {}
    |         ^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:16:9
+  --> $DIR/slice-patterns-reachability.rs:15:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:21:9
+  --> $DIR/slice-patterns-reachability.rs:20:9
    |
 LL |         [false, .., true] => {}
    |         ^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:22:9
+  --> $DIR/slice-patterns-reachability.rs:21:9
    |
 LL |         [false, true] => {}
    |         ^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
index 1484b8c4a1f..363a0e3e649 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/slice.rs
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub fn main() {
     let sl: &[u8] = b"foo";
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
index f1e91a05f08..c234fdf46ed 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/slice.rs:6:11
+  --> $DIR/slice.rs:4:11
    |
 LL |     match sl {
    |           ^^ pattern `&[]` not covered
diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
index 38b0941aad0..33229a205f4 100644
--- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
+++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn slice_pat() {
     let sl: &[u8] = b"foo";
diff --git a/src/test/ui/trailing-comma.rs b/src/test/ui/trailing-comma.rs
index 929c35a9e11..97006ae50a0 100644
--- a/src/test/ui/trailing-comma.rs
+++ b/src/test/ui/trailing-comma.rs
@@ -1,8 +1,6 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![feature(slice_patterns)]
-
 fn f<T,>(_: T,) {}
 
 struct Foo<T,>(T);
diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs
index 1bf01184a08..58c726d2185 100644
--- a/src/test/ui/uninhabited/uninhabited-patterns.rs
+++ b/src/test/ui/uninhabited/uninhabited-patterns.rs
@@ -2,7 +2,7 @@
 #![feature(box_syntax)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![deny(unreachable_patterns)]
 
 mod foo {