Skip to content

Commit

Permalink
librustc: Feature gate subslice matching in non-tail positions.
Browse files Browse the repository at this point in the history
This breaks code that uses the `..xs` form anywhere but at the end of a
slice. For example:

    match foo {
        [ 1, ..xs, 2 ]
        [ ..xs, 1, 2 ]
    }

Add the `#![feature(advanced_slice_patterns)]` gate to reenable the
syntax.

RFC #54.

Closes #16951.

[breaking-change]
  • Loading branch information
pcwalton committed Sep 8, 2014
1 parent 6f34760 commit 22179f4
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 6 deletions.
12 changes: 7 additions & 5 deletions src/doc/rust.md
Expand Up @@ -3290,13 +3290,15 @@ between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has
exactly one argument, while the pattern `C(..)` is type-correct for any enum
variant `C`, regardless of how many arguments `C` has.

Used inside a vector pattern, `..` stands for any number of elements. This
wildcard can be used at most once for a given vector, which implies that it
cannot be used to specifically match elements that are at an unknown distance
from both ends of a vector, like `[.., 42, ..]`. If followed by a variable name,
it will bind the corresponding slice to the variable. Example:
Used inside a vector pattern, `..` stands for any number of elements, when the
`advanced_slice_patterns` feature gate is turned on. This wildcard can be used
at most once for a given vector, which implies that it cannot be used to
specifically match elements that are at an unknown distance from both ends of a
vector, like `[.., 42, ..]`. If followed by a variable name, it will bind the
corresponding slice to the variable. Example:

~~~~
# #![feature(advanced_slice_patterns)]
fn is_symmetric(list: &[uint]) -> bool {
match list {
[] | [_] => true,
Expand Down
15 changes: 15 additions & 0 deletions src/librustc/front/feature_gate.rs
Expand Up @@ -69,6 +69,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("rustc_diagnostic_macros", Active),
("unboxed_closures", Active),
("import_shadowing", Active),
("advanced_slice_patterns", Active),

// if you change this list without updating src/doc/rust.md, cmr will be sad

Expand Down Expand Up @@ -364,6 +365,20 @@ impl<'a> Visitor<()> for Context<'a> {
}
}

fn visit_pat(&mut self, pattern: &ast::Pat, (): ()) {
match pattern.node {
ast::PatVec(_, Some(_), ref last) if !last.is_empty() => {
self.gate_feature("advanced_slice_patterns",
pattern.span,
"multiple-element slice matches anywhere \
but at the end of a slice (e.g. \
`[0, ..xs, 0]` are experimental")
}
_ => {}
}
visit::walk_pat(self, pattern, ())
}

fn visit_fn(&mut self,
fn_kind: &visit::FnKind,
fn_decl: &ast::FnDecl,
Expand Down
2 changes: 2 additions & 0 deletions src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn a<'a>() -> &'a [int] {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/borrowck-vec-pattern-nesting.rs
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn a() {
let mut vec = [box 1i, box 2, box 3];
Expand Down
19 changes: 19 additions & 0 deletions src/test/compile-fail/feature-gate-advanced-slice-features.rs
@@ -0,0 +1,19 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
let x = [ 1i, 2, 3, 4, 5 ];
match x {
[ ..xs, 4, 5 ] => {} //~ ERROR multiple-element slice matches
[ 1, ..xs, 5 ] => {} //~ ERROR multiple-element slice matches
[ 1, 2, ..xs ] => {} // OK without feature gate
}
}

2 changes: 1 addition & 1 deletion src/test/compile-fail/non-exhaustive-pattern-witness.rs
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(struct_variant)]
#![feature(advanced_slice_patterns, struct_variant)]

struct Foo {
first: bool,
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/ignore-all-the-things.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

struct Foo(int, int, int, int);
struct Bar{a: int, b: int, c: int, d: int}

Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/issue-7784.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn foo<T: Add<T, T> + Clone>([x, y, z]: [T, ..3]) -> (T, T, T) {
(x.clone(), x.clone() + y.clone(), x + y + z)
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/match-vec-alternatives.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
match (l1, l2) {
([], []) => "both empty",
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/vec-matching-fixed.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn a() {
let x = [1i, 2, 3];
match x {
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/vec-matching-fold.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn foldl<T,U:Clone>(values: &[T],
initial: U,
function: |partial: U, element: &T| -> U)
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/vec-matching.rs
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(advanced_slice_patterns)]

fn a() {
let x = [1i];
match x {
Expand Down

0 comments on commit 22179f4

Please sign in to comment.