From 22179f49e573edf3616895419f1acd8b93be9cb9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sat, 6 Sep 2014 13:52:07 -0700 Subject: [PATCH] librustc: Feature gate subslice matching in non-tail positions. 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] --- src/doc/rust.md | 12 +++++++----- src/librustc/front/feature_gate.rs | 15 +++++++++++++++ .../borrowck-vec-pattern-element-loan.rs | 2 ++ .../borrowck-vec-pattern-nesting.rs | 1 + .../feature-gate-advanced-slice-features.rs | 19 +++++++++++++++++++ .../non-exhaustive-pattern-witness.rs | 2 +- src/test/run-pass/ignore-all-the-things.rs | 2 ++ src/test/run-pass/issue-7784.rs | 2 ++ src/test/run-pass/match-vec-alternatives.rs | 2 ++ src/test/run-pass/vec-matching-fixed.rs | 2 ++ src/test/run-pass/vec-matching-fold.rs | 2 ++ src/test/run-pass/vec-matching.rs | 2 ++ 12 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/feature-gate-advanced-slice-features.rs diff --git a/src/doc/rust.md b/src/doc/rust.md index 3fd48d4532499..321b7424676e2 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -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, diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index 2305434726599..c83b81660d58f 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -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 @@ -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, diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs index 53ebaa38fddba..62f4f4aaede29 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs @@ -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 diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs index 4a56f9821065b..51e3c612c7171 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs @@ -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]; diff --git a/src/test/compile-fail/feature-gate-advanced-slice-features.rs b/src/test/compile-fail/feature-gate-advanced-slice-features.rs new file mode 100644 index 0000000000000..c6753baf0571e --- /dev/null +++ b/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 or the MIT license +// , 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 + } +} + diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index 6dc5ad8b606c3..7b52e7774d471 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -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, diff --git a/src/test/run-pass/ignore-all-the-things.rs b/src/test/run-pass/ignore-all-the-things.rs index 27c63d425bf38..1c87b6dad8970 100644 --- a/src/test/run-pass/ignore-all-the-things.rs +++ b/src/test/run-pass/ignore-all-the-things.rs @@ -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} diff --git a/src/test/run-pass/issue-7784.rs b/src/test/run-pass/issue-7784.rs index d307a05703843..f45b988b8363b 100644 --- a/src/test/run-pass/issue-7784.rs +++ b/src/test/run-pass/issue-7784.rs @@ -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 + Clone>([x, y, z]: [T, ..3]) -> (T, T, T) { (x.clone(), x.clone() + y.clone(), x + y + z) } diff --git a/src/test/run-pass/match-vec-alternatives.rs b/src/test/run-pass/match-vec-alternatives.rs index de1bb02bfefc6..ae4fd1f1993b7 100644 --- a/src/test/run-pass/match-vec-alternatives.rs +++ b/src/test/run-pass/match-vec-alternatives.rs @@ -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", diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs index 3e9d4b9fc3a24..a1a14823ff595 100644 --- a/src/test/run-pass/vec-matching-fixed.rs +++ b/src/test/run-pass/vec-matching-fixed.rs @@ -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 { diff --git a/src/test/run-pass/vec-matching-fold.rs b/src/test/run-pass/vec-matching-fold.rs index 07ee5f535e9ba..3a55b4b68a9d3 100644 --- a/src/test/run-pass/vec-matching-fold.rs +++ b/src/test/run-pass/vec-matching-fold.rs @@ -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(values: &[T], initial: U, function: |partial: U, element: &T| -> U) diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index e95495a42d282..89d4e3743e367 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -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 {