From 6b98704df66d07fca3483ec834b39042352e0e77 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 8 Nov 2020 16:00:19 -0800 Subject: [PATCH 1/6] Add newer range patterns to unstable book --- .../exclusive-range-pattern.md | 25 +++++++++++++++++++ .../half-open-range-patterns.md | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/exclusive-range-pattern.md create mode 100644 src/doc/unstable-book/src/language-features/half-open-range-patterns.md diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md new file mode 100644 index 0000000000000..a828551aa51bf --- /dev/null +++ b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md @@ -0,0 +1,25 @@ +# `exclusive_range_pattern` + +The tracking issue for this feature is: [#37854]. + + +[#67264]: https://github.com/rust-lang/rust/issues/67264 +[#37854]: https://github.com/rust-lang/rust/issues/37854 +----- + +The `exclusive_range_pattern` feature allows non-inclusive range +patterns (`0..10`) to be used in appropriate pattern matching +contexts. It also can be combined with `#![feature(half_open_range_patterns]` +to be able to use RangeTo patterns (`..10`). + +It also enabled RangeFrom patterns but that has since been +stabilized. + +```rust +#![feature(exclusive_range_pattern)] + match x { + 0..10 => println!("single digit"), + 10 => println!("ten isn't part of the above range"), + _ => println!("nor is everything else.") + } +``` diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md new file mode 100644 index 0000000000000..b6ea510c0fb8e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md @@ -0,0 +1,25 @@ +# `half_open_range_patterns` + +The tracking issue for this feature is: [#67264] +It is part of the `#![exclusive_range_pattern]` feature, +tracked at [#37854]. + +[#67264]: https://github.com/rust-lang/rust/issues/67264 +[#37854]: https://github.com/rust-lang/rust/issues/37854 +----- + +The `half_open_range_patterns` feature allows RangeTo patterns +(`..10`) to be used in appropriate pattern matching contexts. +This requires also enabling the `exclusive_range_pattern` feature. + +It also enabled RangeFrom patterns but that has since been +stabilized. + +```rust +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + match x { + ..10 => println!("got it"), + 0 => println!("zilch") + } +``` From a7e808ed2513013d21d209d3fb8704ad221d6311 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 6 Jan 2021 12:31:34 -0800 Subject: [PATCH 2/6] Add notes --- compiler/rustc_ast/src/ast.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2cffddfcd0b95..6d91c57ff44d3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -675,7 +675,9 @@ pub enum BindingMode { #[derive(Clone, Encodable, Decodable, Debug)] pub enum RangeEnd { + /// `..=` or `...` Included(RangeSyntax), + /// `..` Excluded, } @@ -687,6 +689,7 @@ pub enum RangeSyntax { DotDotEq, } +/// All the different flavors of pattern that Rust recognizes. #[derive(Clone, Encodable, Decodable, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`). @@ -727,7 +730,7 @@ pub enum PatKind { /// A literal. Lit(P), - /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). + /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). Range(Option>, Option>, Spanned), /// A slice pattern `[a, b, c]`. From 91bc117e53bc97cdc60192d16a9ade253d87deb6 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 4 Apr 2021 17:59:31 -0700 Subject: [PATCH 3/6] Allow exclusive range-from patterns --- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3724438cc6ed2..ebc65e90b47d5 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -548,7 +548,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "box pattern syntax is experimental" ); } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { + PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => { gate_feature_post!( &self, exclusive_range_pattern, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 0abefbd6a1219..1ced7eeeebbae 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -715,7 +715,6 @@ impl<'a> Parser<'a> { } else if self.eat(&token::DotDotEq) { RangeEnd::Included(RangeSyntax::DotDotEq) } else if self.eat(&token::DotDot) { - self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_token.span); RangeEnd::Excluded } else { return None; @@ -735,7 +734,6 @@ impl<'a> Parser<'a> { Some(self.parse_pat_range_end()?) } else { // Parsing e.g. `X..`. - self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span)); if let RangeEnd::Included(_) = re.node { // FIXME(Centril): Consider semantic errors instead in `ast_validation`. // Possibly also do this for `X..=` in *expression* contexts. From a3bb9fb8c50b69acf2c8326519a6642e195066a5 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 4 Apr 2021 19:40:40 -0700 Subject: [PATCH 4/6] Add & bless tests --- .../feature-gate-half-open-range-patterns.rs | 8 +-- ...ature-gate-half-open-range-patterns.stderr | 33 +---------- .../range_pat_interactions0.rs | 32 +++++++++++ .../range_pat_interactions1.rs | 29 ++++++++++ .../range_pat_interactions1.stderr | 36 ++++++++++++ .../range_pat_interactions2.rs | 21 +++++++ .../range_pat_interactions2.stderr | 17 ++++++ .../range_pat_interactions3.rs | 24 ++++++++ .../range_pat_interactions3.stderr | 57 +++++++++++++++++++ 9 files changed, 221 insertions(+), 36 deletions(-) create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions0.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions1.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions2.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions3.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs index 1733012b9c54f..9281dda678ddd 100644 --- a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs +++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs @@ -11,12 +11,8 @@ fn foo() { //~| ERROR range-to patterns with `...` are not allowed if let ..5 = 0 {} //~^ ERROR half-open range patterns are unstable - if let 5.. = 0 {} - //~^ ERROR half-open range patterns are unstable if let 5..= = 0 {} - //~^ ERROR half-open range patterns are unstable - //~| ERROR inclusive range with no end + //~^ ERROR inclusive range with no end if let 5... = 0 {} - //~^ ERROR half-open range patterns are unstable - //~| ERROR inclusive range with no end + //~^ ERROR inclusive range with no end } diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr index 62d54463a433c..a04883ae14764 100644 --- a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr +++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr @@ -5,7 +5,7 @@ LL | if let ...5 = 0 {} | ^^^ help: use `..=` instead error[E0586]: inclusive range with no end - --> $DIR/feature-gate-half-open-range-patterns.rs:16:13 + --> $DIR/feature-gate-half-open-range-patterns.rs:14:13 | LL | if let 5..= = 0 {} | ^^^ help: use `..` instead @@ -13,7 +13,7 @@ LL | if let 5..= = 0 {} = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end - --> $DIR/feature-gate-half-open-range-patterns.rs:19:13 + --> $DIR/feature-gate-half-open-range-patterns.rs:16:13 | LL | if let 5... = 0 {} | ^^^ help: use `..` instead @@ -47,34 +47,7 @@ LL | if let ..5 = 0 {} = note: see issue #67264 for more information = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable -error[E0658]: half-open range patterns are unstable - --> $DIR/feature-gate-half-open-range-patterns.rs:14:12 - | -LL | if let 5.. = 0 {} - | ^^^ - | - = note: see issue #67264 for more information - = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable - -error[E0658]: half-open range patterns are unstable - --> $DIR/feature-gate-half-open-range-patterns.rs:16:12 - | -LL | if let 5..= = 0 {} - | ^^^^ - | - = note: see issue #67264 for more information - = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable - -error[E0658]: half-open range patterns are unstable - --> $DIR/feature-gate-half-open-range-patterns.rs:19:12 - | -LL | if let 5... = 0 {} - | ^^^^ - | - = note: see issue #67264 for more information - = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable - -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0586, E0658. For more information about an error, try `rustc --explain E0586`. diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs new file mode 100644 index 0000000000000..4f478a6988142 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(incomplete_features)] +#![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] +#![feature(inline_const)] + +fn main() { + let mut if_lettable = vec![]; + let mut first_or = vec![]; + let mut or_two = vec![]; + let mut range_from = vec![]; + let mut bottom = vec![]; + + for x in -9 + 1..=(9 - 2) { + if let -1..=0 | 2..3 | 4 = x { + if_lettable.push(x) + } + match x { + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } + assert_eq!(if_lettable, [-1, 0, 2, 4]); + assert_eq!(first_or, [-3, -2, -1, 1]); + assert_eq!(or_two, [0, 2, 3, 4, 6]); + assert_eq!(range_from, [-5, -4, 7]); + assert_eq!(bottom, [-7, -6]); +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs new file mode 100644 index 0000000000000..55353999b6788 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -0,0 +1,29 @@ +fn main() { + let mut if_lettable = Vec::::new(); + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + if let n @ 2..3|4 = x { + //~^ error: variable `n` is not bound in all patterns + //~| exclusive range pattern syntax is experimental + errors_only.push(x); + } else if let 2..3 | 4 = x { + //~^ exclusive range pattern syntax is experimental + if_lettable.push(x); + } + match x as i32 { + 0..5+1 => errors_only.push(x), + //~^ error: expected one of `=>`, `if`, or `|`, found `+` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr new file mode 100644 index 0000000000000..19ebcaf0f3699 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -0,0 +1,36 @@ +error: expected one of `=>`, `if`, or `|`, found `+` + --> $DIR/range_pat_interactions1.rs:19:17 + | +LL | 0..5+1 => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error[E0408]: variable `n` is not bound in all patterns + --> $DIR/range_pat_interactions1.rs:10:25 + | +LL | if let n @ 2..3|4 = x { + | - ^ pattern doesn't bind `n` + | | + | variable not in all patterns + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:10:20 + | +LL | if let n @ 2..3|4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:14:23 + | +LL | } else if let 2..3 | 4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0408, E0658. +For more information about an error, try `rustc --explain E0408`. diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs new file mode 100644 index 0000000000000..4615ebd688a9c --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -0,0 +1,21 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 0..=(5+1) => errors_only.push(x), + //~^ error: inclusive range with no end + //~| error: expected one of `=>`, `if`, or `|`, found `(` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr new file mode 100644 index 0000000000000..13a5542a4741f --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -0,0 +1,17 @@ +error[E0586]: inclusive range with no end + --> $DIR/range_pat_interactions2.rs:10:14 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `(` + --> $DIR/range_pat_interactions2.rs:10:17 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs new file mode 100644 index 0000000000000..0afb512605912 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs @@ -0,0 +1,24 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 8.. => bottom.push(x), + 1 | -3..0 => first_or.push(x), + //~^ exclusive range pattern syntax is experimental + y @ (0..5 | 6) => or_two.push(y), + //~^ exclusive range pattern syntax is experimental + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + //~^ inline-const is experimental + //~| exclusive range pattern syntax is experimental + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + //~^ half-open range patterns are unstable + //~| exclusive range pattern syntax is experimental + y => bottom.push(y), + } + } +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr new file mode 100644 index 0000000000000..8278e7cc6cfde --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr @@ -0,0 +1,57 @@ +error[E0658]: half-open range patterns are unstable + --> $DIR/range_pat_interactions3.rs:18:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: inline-const is experimental + --> $DIR/range_pat_interactions3.rs:14:20 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:10:17 + | +LL | 1 | -3..0 => first_or.push(x), + | ^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:12:18 + | +LL | y @ (0..5 | 6) => or_two.push(y), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:14:17 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:18:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. From 45d9dd69a7724986f1b80cf9462323b48d4e2529 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 6 Apr 2021 10:51:06 -0700 Subject: [PATCH 5/6] Satisfy unstable book lint --- .../src/language-features/exclusive-range-pattern.md | 1 + .../src/language-features/half-open-range-patterns.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md index a828551aa51bf..d26512703f494 100644 --- a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md +++ b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md @@ -17,6 +17,7 @@ stabilized. ```rust #![feature(exclusive_range_pattern)] + let x = 5; match x { 0..10 => println!("single digit"), 10 => println!("ten isn't part of the above range"), diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md index b6ea510c0fb8e..3b16dd049ce33 100644 --- a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md +++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md @@ -18,8 +18,10 @@ stabilized. ```rust #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] + let x = 5; match x { - ..10 => println!("got it"), - 0 => println!("zilch") + ..0 => println!("negative!"), // "RangeTo" pattern. Unstable. + 0 => println!("zero!"), + 1.. => println!("positive!"), // "RangeFrom" pattern. Stable. } ``` From 43bad44ff01dd5035b961b366e65f705241b428d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 27 May 2021 14:36:45 -0700 Subject: [PATCH 6/6] Reestablish feature gate for RangeFrom in slices --- compiler/rustc_ast_passes/src/feature_gate.rs | 16 ++++++++ .../slice_pattern_syntax_problem0.rs | 16 ++++++++ .../slice_pattern_syntax_problem0.stderr | 9 +++++ .../slice_pattern_syntax_problem1.rs | 9 +++++ .../slice_pattern_syntax_problem1.stderr | 39 +++++++++++++++++++ .../slice_pattern_syntax_problem2.rs | 10 +++++ 6 files changed, 99 insertions(+) create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ebc65e90b47d5..4316996e4f0ed 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -540,6 +540,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_pat(&mut self, pattern: &'a ast::Pat) { match &pattern.kind { + PatKind::Slice(pats) => { + for pat in pats { + let inner_pat = match &pat.kind { + PatKind::Ident(.., Some(pat)) => pat, + _ => pat, + }; + if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { + gate_feature_post!( + &self, + half_open_range_patterns, + pat.span, + "`X..` patterns in slices are experimental" + ); + } + } + } PatKind::Box(..) => { gate_feature_post!( &self, diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs new file mode 100644 index 0000000000000..2884a27349fbb --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs @@ -0,0 +1,16 @@ +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a, b, c, rest @ ..] = xs; + // Consider the following example: + assert!(a == 13 && b == 1 && c == 5 && rest.len() == 5); + + // What if we wanted to pull this apart without individually binding a, b, and c? + let [first_three @ ..3, rest @ 2..] = xs; + //~^ pattern requires 2 elements but array has 8 + // This is somewhat unintuitive and makes slice patterns exceedingly verbose. + // We want to stabilize half-open RangeFrom (`X..`) patterns + // but without banning us from using them for a more efficient slice pattern syntax. +} diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr new file mode 100644 index 0000000000000..ec3472a503684 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 2 elements but array has 8 + --> $DIR/slice_pattern_syntax_problem0.rs:11:9 + | +LL | let [first_three @ ..3, rest @ 2..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs new file mode 100644 index 0000000000000..9e289b591d6e9 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -0,0 +1,9 @@ +// Instead of allowing the previous case, maintain the feature gate for slice patterns for now. +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + //~^ `X..` patterns in slices are experimental + //~| half-open range patterns are unstable + //~| exclusive range pattern syntax is experimental + //~| exclusive range pattern syntax is experimental +} diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr new file mode 100644 index 0000000000000..eadaf87767069 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -0,0 +1,39 @@ +error[E0658]: half-open range patterns are unstable + --> $DIR/slice_pattern_syntax_problem1.rs:4:23 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:10 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:23 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:32 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs new file mode 100644 index 0000000000000..6e7df30949127 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs @@ -0,0 +1,10 @@ +// run-pass + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + if let [3..=14, ..] = xs { + /* this variant must pass for now, unfortunately. + * This test is included here to help inform a future plan for these. + */ + }; +}