From c038b454239a30cb8a734bcb2ff8a7e5e543939a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Date: Sun, 6 Mar 2016 15:54:44 +0300 Subject: [PATCH] Address review comments --- src/librustc/hir/mod.rs | 4 +- src/librustc/hir/pat_util.rs | 8 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/parse/parser.rs | 4 + src/test/parse-fail/pat-tuple-3.rs | 2 +- src/test/run-pass/pat-tuple-1.rs | 104 +++++++++++++++ src/test/run-pass/pat-tuple-2.rs | 34 +++++ src/test/run-pass/pat-tuple-3.rs | 40 ++++++ src/test/run-pass/pat-tuple-4.rs | 68 ++++++++++ src/test/run-pass/pat-tuple-5.rs | 40 ++++++ src/test/run-pass/pat-tuple-6.rs | 56 ++++++++ src/test/run-pass/pat-tuple.rs | 202 ----------------------------- 12 files changed, 355 insertions(+), 211 deletions(-) create mode 100644 src/test/run-pass/pat-tuple-1.rs create mode 100644 src/test/run-pass/pat-tuple-2.rs create mode 100644 src/test/run-pass/pat-tuple-3.rs create mode 100644 src/test/run-pass/pat-tuple-4.rs create mode 100644 src/test/run-pass/pat-tuple-5.rs create mode 100644 src/test/run-pass/pat-tuple-6.rs delete mode 100644 src/test/run-pass/pat-tuple.rs diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 961885d1b86..dff17d8c17b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -539,7 +539,7 @@ pub enum PatKind { Struct(Path, HirVec<Spanned<FieldPat>>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. - /// If the `..` pattern fragment presents, then `Option<usize>` denotes its position. + /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// 0 <= position <= subpats.len() TupleStruct(Path, HirVec<P<Pat>>, Option<usize>), @@ -554,7 +554,7 @@ pub enum PatKind { QPath(QSelf, Path), /// A tuple pattern `(a, b)`. - /// If the `..` pattern fragment presents, then `Option<usize>` denotes its position. + /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// 0 <= position <= subpats.len() Tuple(HirVec<P<Pat>>, Option<usize>), /// A `box` pattern diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index f41c4b0840d..cf4842a25d6 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -22,12 +22,12 @@ use std::cell::RefCell; pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>; #[derive(Clone, Copy)] -pub struct AjustPos { +pub struct AdjustPos { gap_pos: usize, gap_len: usize, } -impl FnOnce<(usize,)> for AjustPos { +impl FnOnce<(usize,)> for AdjustPos { type Output = usize; extern "rust-call" fn call_once(self, (i,): (usize,)) -> usize { if i < self.gap_pos { i } else { i + self.gap_len } @@ -36,8 +36,8 @@ impl FnOnce<(usize,)> for AjustPos { // Returns a functional object used to adjust tuple pattern indexes. Example: for 5-tuple and // pattern (a, b, .., c) expected_len is 5, actual_len is 3 and gap_pos is Some(2). -pub fn pat_adjust_pos(expected_len: usize, actual_len: usize, gap_pos: Option<usize>) -> AjustPos { - AjustPos { +pub fn pat_adjust_pos(expected_len: usize, actual_len: usize, gap_pos: Option<usize>) -> AdjustPos { + AdjustPos { gap_pos: if let Some(gap_pos) = gap_pos { gap_pos } else { expected_len }, gap_len: expected_len - actual_len, } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 6eb588767c4..7c3c33c28f6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -631,7 +631,7 @@ pub enum PatKind { Struct(Path, Vec<Spanned<FieldPat>>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. - /// If the `..` pattern fragment presents, then `Option<usize>` denotes its position. + /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// 0 <= position <= subpats.len() TupleStruct(Path, Vec<P<Pat>>, Option<usize>), @@ -646,7 +646,7 @@ pub enum PatKind { QPath(QSelf, Path), /// A tuple pattern `(a, b)`. - /// If the `..` pattern fragment presents, then `Option<usize>` denotes its position. + /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// 0 <= position <= subpats.len() Tuple(Vec<P<Pat>>, Option<usize>), /// A `box` pattern diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a4f12769b5c..943910b1570 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3426,6 +3426,10 @@ impl<'a> Parser<'a> { // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. fields.push(self.parse_pat()?); } + } else if ddpos.is_some() && self.eat(&token::DotDot) { + // Emit a friendly error, ignore `..` and continue parsing + self.span_err(self.last_span, "`..` can only be used once per \ + tuple or tuple struct pattern"); } else { fields.push(self.parse_pat()?); } diff --git a/src/test/parse-fail/pat-tuple-3.rs b/src/test/parse-fail/pat-tuple-3.rs index 95e44ae134c..029dc7a2956 100644 --- a/src/test/parse-fail/pat-tuple-3.rs +++ b/src/test/parse-fail/pat-tuple-3.rs @@ -12,6 +12,6 @@ fn main() { match 0 { - (.., pat, ..) => {} //~ ERROR expected pattern, found `..` + (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern } } diff --git a/src/test/run-pass/pat-tuple-1.rs b/src/test/run-pass/pat-tuple-1.rs new file mode 100644 index 00000000000..c3796210a8e --- /dev/null +++ b/src/test/run-pass/pat-tuple-1.rs @@ -0,0 +1,104 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + match x { + (a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + (.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + (a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + S(.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-2.rs b/src/test/run-pass/pat-tuple-2.rs new file mode 100644 index 00000000000..881e96a9d78 --- /dev/null +++ b/src/test/run-pass/pat-tuple-2.rs @@ -0,0 +1,34 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1,); + match x { + (2, ..) => panic!(), + (..) => () + } +} + +fn tuple_struct() { + struct S(u8); + + let x = S(1); + match x { + S(2, ..) => panic!(), + S(..) => () + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-3.rs b/src/test/run-pass/pat-tuple-3.rs new file mode 100644 index 00000000000..94d33d41899 --- /dev/null +++ b/src/test/run-pass/pat-tuple-3.rs @@ -0,0 +1,40 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + let branch = match x { + (1, 1, ..) => 0, + (1, 2, 3, ..) => 1, + (1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + let branch = match x { + S(1, 1, ..) => 0, + S(1, 2, 3, ..) => 1, + S(1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-4.rs b/src/test/run-pass/pat-tuple-4.rs new file mode 100644 index 00000000000..ffd82fea996 --- /dev/null +++ b/src/test/run-pass/pat-tuple-4.rs @@ -0,0 +1,68 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + match x { + (1, 2, 4) => unreachable!(), + (0, 2, 3, ..) => unreachable!(), + (0, .., 3) => unreachable!(), + (0, ..) => unreachable!(), + (1, 2, 3) => (), + (_, _, _) => unreachable!(), + } + match x { + (..) => (), + } + match x { + (_, _, _, ..) => (), + } + match x { + (a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(1, 2, 4) => unreachable!(), + S(0, 2, 3, ..) => unreachable!(), + S(0, .., 3) => unreachable!(), + S(0, ..) => unreachable!(), + S(1, 2, 3) => (), + S(_, _, _) => unreachable!(), + } + match x { + S(..) => (), + } + match x { + S(_, _, _, ..) => (), + } + match x { + S(a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-5.rs b/src/test/run-pass/pat-tuple-5.rs new file mode 100644 index 00000000000..41c4d02abcb --- /dev/null +++ b/src/test/run-pass/pat-tuple-5.rs @@ -0,0 +1,40 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + struct S; + struct Z; + struct W; + let x = (S, Z, W); + match x { (S, ..) => {} } + match x { (.., W) => {} } + match x { (S, .., W) => {} } + match x { (.., Z, _) => {} } +} + +fn tuple_struct() { + struct SS(S, Z, W); + + struct S; + struct Z; + struct W; + let x = SS(S, Z, W); + match x { SS(S, ..) => {} } + match x { SS(.., W) => {} } + match x { SS(S, .., W) => {} } + match x { SS(.., Z, _) => {} } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-6.rs b/src/test/run-pass/pat-tuple-6.rs new file mode 100644 index 00000000000..6f3f2b3aed5 --- /dev/null +++ b/src/test/run-pass/pat-tuple-6.rs @@ -0,0 +1,56 @@ +// Copyright 2016 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. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3, 4, 5); + match x { + (a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + (a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8, u8, u8); + + let x = S(1, 2, 3, 4, 5); + match x { + S(a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + S(a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple.rs b/src/test/run-pass/pat-tuple.rs deleted file mode 100644 index ccea068f715..00000000000 --- a/src/test/run-pass/pat-tuple.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2016 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. - -#![feature(dotdot_in_tuple_patterns)] - -fn b() { - let x = (1, 2, 3); - match x { - (a, b, ..) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - } - } - match x { - (.., b, c) => { - assert_eq!(b, 2); - assert_eq!(c, 3); - } - } - match x { - (a, .., c) => { - assert_eq!(a, 1); - assert_eq!(c, 3); - } - } - match x { - (a, b, c) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - assert_eq!(c, 3); - } - } -} - -fn bs() { - struct S(u8, u8, u8); - - let x = S(1, 2, 3); - match x { - S(a, b, ..) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - } - } - match x { - S(.., b, c) => { - assert_eq!(b, 2); - assert_eq!(c, 3); - } - } - match x { - S(a, .., c) => { - assert_eq!(a, 1); - assert_eq!(c, 3); - } - } - match x { - S(a, b, c) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - assert_eq!(c, 3); - } - } -} - -fn c() { - let x = (1,); - match x { - (2, ..) => panic!(), - (..) => () - } -} - -fn cs() { - struct S(u8); - - let x = S(1); - match x { - S(2, ..) => panic!(), - S(..) => () - } -} - -fn d() { - let x = (1, 2, 3); - let branch = match x { - (1, 1, ..) => 0, - (1, 2, 3, ..) => 1, - (1, 2, ..) => 2, - _ => 3 - }; - assert_eq!(branch, 1); -} - -fn ds() { - struct S(u8, u8, u8); - - let x = S(1, 2, 3); - let branch = match x { - S(1, 1, ..) => 0, - S(1, 2, 3, ..) => 1, - S(1, 2, ..) => 2, - _ => 3 - }; - assert_eq!(branch, 1); -} - -fn f() { - let x = (1, 2, 3); - match x { - (1, 2, 4) => unreachable!(), - (0, 2, 3, ..) => unreachable!(), - (0, .., 3) => unreachable!(), - (0, ..) => unreachable!(), - (1, 2, 3) => (), - (_, _, _) => unreachable!(), - } - match x { - (..) => (), - } - match x { - (_, _, _, ..) => (), - } - match x { - (a, b, c) => { - assert_eq!(1, a); - assert_eq!(2, b); - assert_eq!(3, c); - } - } -} - -fn fs() { - struct S(u8, u8, u8); - - let x = S(1, 2, 3); - match x { - S(1, 2, 4) => unreachable!(), - S(0, 2, 3, ..) => unreachable!(), - S(0, .., 3) => unreachable!(), - S(0, ..) => unreachable!(), - S(1, 2, 3) => (), - S(_, _, _) => unreachable!(), - } - match x { - S(..) => (), - } - match x { - S(_, _, _, ..) => (), - } - match x { - S(a, b, c) => { - assert_eq!(1, a); - assert_eq!(2, b); - assert_eq!(3, c); - } - } -} - -fn g() { - struct S; - struct Z; - struct W; - let x = (S, Z, W); - match x { (S, ..) => {} } - match x { (.., W) => {} } - match x { (S, .., W) => {} } - match x { (.., Z, _) => {} } -} - -fn gs() { - struct SS(S, Z, W); - - struct S; - struct Z; - struct W; - let x = SS(S, Z, W); - match x { SS(S, ..) => {} } - match x { SS(.., W) => {} } - match x { SS(S, .., W) => {} } - match x { SS(.., Z, _) => {} } -} - -fn main() { - b(); - bs(); - c(); - cs(); - d(); - ds(); - f(); - fs(); - g(); - gs(); -}