Auto merge of #61708 - dlrobertson:or-patterns-0, r=centril
Initial implementation of or-patterns
An incomplete implementation of or-patterns (e.g. `Some(0 | 1)` as a pattern). This patch set aims to implement initial parsing of `or-patterns`.
Related to: #54883
CC @alexreg @varkor
r? @Centril
diff --git a/src/doc/unstable-book/src/language-features/or-patterns.md b/src/doc/unstable-book/src/language-features/or-patterns.md
new file mode 100644
index 0000000..8ebacb4
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/or-patterns.md
@@ -0,0 +1,36 @@
+# `or_patterns`
+
+The tracking issue for this feature is: [#54883]
+
+[#54883]: https://github.com/rust-lang/rust/issues/54883
+
+------------------------
+
+The `or_pattern` language feature allows `|` to be arbitrarily nested within
+a pattern, for example, `Some(A(0) | B(1 | 2))` becomes a valid pattern.
+
+## Examples
+
+```rust,ignore
+#![feature(or_patterns)]
+
+pub enum Foo {
+ Bar,
+ Baz,
+ Quux,
+}
+
+pub fn example(maybe_foo: Option<Foo>) {
+ match maybe_foo {
+ Some(Foo::Bar | Foo::Baz) => {
+ println!("The value contained `Bar` or `Baz`");
+ }
+ Some(_) => {
+ println!("The value did not contain `Bar` or `Baz`");
+ }
+ None => {
+ println!("The value was `None`");
+ }
+ }
+}
+```
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 7ada56c..0dad2dd 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -140,6 +140,11 @@
self.add_ast_node(pat.hir_id.local_id, &[pats_exit])
}
+ PatKind::Or(ref pats) => {
+ let branches: Vec<_> = pats.iter().map(|p| self.pat(p, pred)).collect();
+ self.add_ast_node(pat.hir_id.local_id, &branches)
+ }
+
PatKind::Slice(ref pre, ref vec, ref post) => {
let pre_exit = self.pats_all(pre.iter(), pred);
let vec_exit = self.pats_all(vec.iter(), pre_exit);
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 99fe9f1..2c6373b 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -709,6 +709,7 @@
visitor.visit_pat(&field.pat)
}
}
+ PatKind::Or(ref pats) => walk_list!(visitor, visit_pat, pats),
PatKind::Tuple(ref tuple_elements, _) => {
walk_list!(visitor, visit_pat, tuple_elements);
}
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 0f6e834..d2ea485 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2669,6 +2669,9 @@
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
hir::PatKind::TupleStruct(qpath, pats, ddpos)
}
+ PatKind::Or(ref pats) => {
+ hir::PatKind::Or(pats.iter().map(|x| self.lower_pat(x)).collect())
+ }
PatKind::Path(ref qself, ref path) => {
let qpath = self.lower_qpath(
p.id,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index e5ada1f..b469b70 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -881,6 +881,7 @@
PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
s.iter().all(|p| p.walk_(it))
}
+ PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)),
PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
s.walk_(it)
}
@@ -975,6 +976,10 @@
/// `0 <= position <= subpats.len()`
TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>),
+ /// An or-pattern `A | B | C`.
+ /// Invariant: `pats.len() >= 2`.
+ Or(HirVec<P<Pat>>),
+
/// A path pattern for an unit struct/variant or a (maybe-associated) constant.
Path(QPath),
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 2fd683e..632a13f 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1687,6 +1687,9 @@
self.s.space();
self.s.word("}");
}
+ PatKind::Or(ref pats) => {
+ self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p));
+ }
PatKind::Tuple(ref elts, ddpos) => {
self.popen();
if let Some(ddpos) = ddpos {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index a55803e..73ca981 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1290,6 +1290,12 @@
}
}
+ PatKind::Or(ref pats) => {
+ for pat in pats {
+ self.cat_pattern_(cmt.clone(), &pat, op)?;
+ }
+ }
+
PatKind::Binding(.., Some(ref subpat)) => {
self.cat_pattern_(cmt, &subpat, op)?;
}
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index d72b0ad..94323b1 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -657,6 +657,11 @@
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
}
}
+ PatternKind::Or { ref pats } => {
+ for pat in pats {
+ self.visit_bindings(&pat, pattern_user_ty.clone(), f);
+ }
+ }
}
}
}
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index 3473155..8d049b5 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -195,6 +195,10 @@
candidate.match_pairs.push(MatchPair::new(place, subpattern));
Ok(())
}
+
+ PatternKind::Or { .. } => {
+ Err(match_pair)
+ }
}
}
}
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 65e92d4..ec85dac 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -87,6 +87,7 @@
PatternKind::AscribeUserType { .. } |
PatternKind::Array { .. } |
PatternKind::Wild |
+ PatternKind::Or { .. } |
PatternKind::Binding { .. } |
PatternKind::Leaf { .. } |
PatternKind::Deref { .. } => {
@@ -130,6 +131,7 @@
PatternKind::Slice { .. } |
PatternKind::Array { .. } |
PatternKind::Wild |
+ PatternKind::Or { .. } |
PatternKind::Binding { .. } |
PatternKind::AscribeUserType { .. } |
PatternKind::Leaf { .. } |
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 1833ee3..222750e 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1359,6 +1359,9 @@
Some(vec![Slice(pat_len)])
}
}
+ PatternKind::Or { .. } => {
+ bug!("support for or-patterns has not been fully implemented yet.");
+ }
}
}
@@ -1884,6 +1887,10 @@
"unexpected ctor {:?} for slice pat", constructor)
}
}
+
+ PatternKind::Or { .. } => {
+ bug!("support for or-patterns has not been fully implemented yet.");
+ }
};
debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head);
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index bebb071..6caccfd 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -175,6 +175,12 @@
slice: Option<Pattern<'tcx>>,
suffix: Vec<Pattern<'tcx>>,
},
+
+ /// An or-pattern, e.g. `p | q`.
+ /// Invariant: `pats.len() >= 2`.
+ Or {
+ pats: Vec<Pattern<'tcx>>,
+ },
}
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -186,6 +192,18 @@
impl<'tcx> fmt::Display for Pattern<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Printing lists is a chore.
+ let mut first = true;
+ let mut start_or_continue = |s| {
+ if first {
+ first = false;
+ ""
+ } else {
+ s
+ }
+ };
+ let mut start_or_comma = || start_or_continue(", ");
+
match *self.kind {
PatternKind::Wild => write!(f, "_"),
PatternKind::AscribeUserType { ref subpattern, .. } =>
@@ -224,9 +242,6 @@
}
};
- let mut first = true;
- let mut start_or_continue = || if first { first = false; "" } else { ", " };
-
if let Some(variant) = variant {
write!(f, "{}", variant.ident)?;
@@ -241,12 +256,12 @@
continue;
}
let name = variant.fields[p.field.index()].ident;
- write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?;
+ write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
printed += 1;
}
if printed < variant.fields.len() {
- write!(f, "{}..", start_or_continue())?;
+ write!(f, "{}..", start_or_comma())?;
}
return write!(f, " }}");
@@ -257,7 +272,7 @@
if num_fields != 0 || variant.is_none() {
write!(f, "(")?;
for i in 0..num_fields {
- write!(f, "{}", start_or_continue())?;
+ write!(f, "{}", start_or_comma())?;
// Common case: the field is where we expect it.
if let Some(p) = subpatterns.get(i) {
@@ -305,14 +320,12 @@
}
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
- let mut first = true;
- let mut start_or_continue = || if first { first = false; "" } else { ", " };
write!(f, "[")?;
for p in prefix {
- write!(f, "{}{}", start_or_continue(), p)?;
+ write!(f, "{}{}", start_or_comma(), p)?;
}
if let Some(ref slice) = *slice {
- write!(f, "{}", start_or_continue())?;
+ write!(f, "{}", start_or_comma())?;
match *slice.kind {
PatternKind::Wild => {}
_ => write!(f, "{}", slice)?
@@ -320,10 +333,16 @@
write!(f, "..")?;
}
for p in suffix {
- write!(f, "{}{}", start_or_continue(), p)?;
+ write!(f, "{}{}", start_or_comma(), p)?;
}
write!(f, "]")
}
+ PatternKind::Or { ref pats } => {
+ for pat in pats {
+ write!(f, "{}{}", start_or_continue(" | "), pat)?;
+ }
+ Ok(())
+ }
}
}
}
@@ -655,6 +674,12 @@
self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
}
+
+ PatKind::Or(ref pats) => {
+ PatternKind::Or {
+ pats: pats.iter().map(|p| self.lower_pattern(p)).collect(),
+ }
+ }
};
Pattern {
@@ -1436,6 +1461,7 @@
slice: slice.fold_with(folder),
suffix: suffix.fold_with(folder)
},
+ PatternKind::Or { ref pats } => PatternKind::Or { pats: pats.fold_with(folder) },
}
}
}
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 99ae777..fc25eb4 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -53,6 +53,7 @@
let is_non_ref_pat = match pat.node {
PatKind::Struct(..) |
PatKind::TupleStruct(..) |
+ PatKind::Or(_) |
PatKind::Tuple(..) |
PatKind::Box(_) |
PatKind::Range(..) |
@@ -309,6 +310,13 @@
PatKind::Struct(ref qpath, ref fields, etc) => {
self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
}
+ PatKind::Or(ref pats) => {
+ let expected_ty = self.structurally_resolved_type(pat.span, expected);
+ for pat in pats {
+ self.check_pat_walk(pat, expected, def_bm, discrim_span);
+ }
+ expected_ty
+ }
PatKind::Tuple(ref elements, ddpos) => {
let mut expected_len = elements.len();
if ddpos.is_some() {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fede9e9..023d228 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -4107,6 +4107,9 @@
if etc { ", .." } else { "" }
)
}
+ PatKind::Or(ref pats) => {
+ pats.iter().map(|p| name_from_pat(&**p)).collect::<Vec<String>>().join(" | ")
+ }
PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
.collect::<Vec<String>>().join(", ")),
PatKind::Box(ref p) => name_from_pat(&**p),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9091607..50e428e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -572,9 +572,10 @@
match &self.node {
PatKind::Ident(_, _, Some(p)) => p.walk(it),
PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk(it)),
- PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => {
- s.iter().all(|p| p.walk(it))
- }
+ PatKind::TupleStruct(_, s)
+ | PatKind::Tuple(s)
+ | PatKind::Slice(s)
+ | PatKind::Or(s) => s.iter().all(|p| p.walk(it)),
PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
PatKind::Wild
| PatKind::Rest
@@ -648,6 +649,10 @@
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
TupleStruct(Path, Vec<P<Pat>>),
+ /// An or-pattern `A | B | C`.
+ /// Invariant: `pats.len() >= 2`.
+ Or(Vec<P<Pat>>),
+
/// A possibly qualified path pattern.
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
/// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 1a87a90..bbc3ae2 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -559,6 +559,9 @@
// Allows `impl Trait` to be used inside type aliases (RFC 2515).
(active, type_alias_impl_trait, "1.38.0", Some(63063), None),
+ // Allows the use of or-patterns, e.g. `0 | 1`.
+ (active, or_patterns, "1.38.0", Some(54883), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
@@ -571,6 +574,7 @@
sym::impl_trait_in_bindings,
sym::generic_associated_types,
sym::const_generics,
+ sym::or_patterns,
sym::let_chains,
];
@@ -2443,6 +2447,7 @@
gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental");
gate_all!(async_closure_spans, async_closure, "async closures are unstable");
gate_all!(yield_spans, generators, "yield syntax is experimental");
+ gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental");
let visitor = &mut PostExpansionVisitor {
context: &ctx,
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 18d4a64..9785f8e 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1050,7 +1050,6 @@
vis.visit_span(span);
};
}
- PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
PatKind::Box(inner) => vis.visit_pat(inner),
PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
@@ -1058,7 +1057,9 @@
vis.visit_expr(e2);
vis.visit_span(span);
}
- PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
+ PatKind::Tuple(elems)
+ | PatKind::Slice(elems)
+ | PatKind::Or(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
PatKind::Paren(inner) => vis.visit_pat(inner),
PatKind::Mac(mac) => vis.visit_mac(mac),
}
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 9088f92..b1f3612 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -66,6 +66,8 @@
// Places where `yield e?` exprs were used and should be feature gated.
pub yield_spans: Lock<Vec<Span>>,
pub injected_crate_name: Once<Symbol>,
+ // Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated.
+ pub or_pattern_spans: Lock<Vec<Span>>,
}
impl ParseSess {
@@ -96,6 +98,7 @@
async_closure_spans: Lock::new(Vec::new()),
yield_spans: Lock::new(Vec::new()),
injected_crate_name: Once::new(),
+ or_pattern_spans: Lock::new(Vec::new()),
}
}
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs
index c3079d2..fd458ae 100644
--- a/src/libsyntax/parse/parser/pat.rs
+++ b/src/libsyntax/parse/parser/pat.rs
@@ -14,7 +14,10 @@
impl<'a> Parser<'a> {
/// Parses a pattern.
- pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> {
+ pub fn parse_pat(
+ &mut self,
+ expected: Option<&'static str>
+ ) -> PResult<'a, P<Pat>> {
self.parse_pat_with_range_pat(true, expected)
}
@@ -97,6 +100,34 @@
Ok(())
}
+ /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`).
+ fn parse_pat_with_or(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> {
+ // Parse the first pattern.
+ let first_pat = self.parse_pat(expected)?;
+
+ // If the next token is not a `|`, this is not an or-pattern and
+ // we should exit here.
+ if !self.check(&token::BinOp(token::Or)) {
+ return Ok(first_pat)
+ }
+
+ let lo = first_pat.span;
+
+ let mut pats = vec![first_pat];
+
+ while self.eat(&token::BinOp(token::Or)) {
+ pats.push(self.parse_pat_with_range_pat(
+ true, expected
+ )?);
+ }
+
+ let or_pattern_span = lo.to(self.prev_span);
+
+ self.sess.or_pattern_spans.borrow_mut().push(or_pattern_span);
+
+ Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
+ }
+
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
/// allowed).
fn parse_pat_with_range_pat(
@@ -240,7 +271,9 @@
/// Parse a tuple or parenthesis pattern.
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
- let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+ let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
+ p.parse_pat_with_or(None)
+ })?;
// Here, `(pat,)` is a tuple pattern.
// For backward compatibility, `(..)` is a tuple pattern as well.
@@ -483,7 +516,7 @@
err.span_label(self.token.span, msg);
return Err(err);
}
- let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+ let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None))?;
Ok(PatKind::TupleStruct(path, fields))
}
@@ -627,7 +660,7 @@
// Parsing a pattern of the form "fieldname: pat"
let fieldname = self.parse_field_name()?;
self.bump();
- let pat = self.parse_pat(None)?;
+ let pat = self.parse_pat_with_or(None)?;
hi = pat.span;
(pat, fieldname, false)
} else {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8a70098..4dc00af 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -436,18 +436,30 @@
fn print_ident(&mut self, ident: ast::Ident);
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
- fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F)
+ fn strsep<T, F>(&mut self, sep: &'static str, space_before: bool,
+ b: Breaks, elts: &[T], mut op: F)
where F: FnMut(&mut Self, &T),
{
self.rbox(0, b);
- let mut first = true;
- for elt in elts {
- if first { first = false; } else { self.word_space(","); }
- op(self, elt);
+ if let Some((first, rest)) = elts.split_first() {
+ op(self, first);
+ for elt in rest {
+ if space_before {
+ self.space();
+ }
+ self.word_space(sep);
+ op(self, elt);
+ }
}
self.end();
}
+ fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F)
+ where F: FnMut(&mut Self, &T),
+ {
+ self.strsep(",", false, b, elts, op)
+ }
+
fn maybe_print_comment(&mut self, pos: BytePos) {
while let Some(ref cmnt) = self.next_comment() {
if cmnt.pos < pos {
@@ -2353,6 +2365,9 @@
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
self.pclose();
}
+ PatKind::Or(ref pats) => {
+ self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p));
+ }
PatKind::Path(None, ref path) => {
self.print_path(path, true, 0);
}
@@ -2429,16 +2444,7 @@
}
fn print_pats(&mut self, pats: &[P<ast::Pat>]) {
- let mut first = true;
- for p in pats {
- if first {
- first = false;
- } else {
- self.s.space();
- self.word_space("|");
- }
- self.print_pat(p);
- }
+ self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p));
}
fn print_arm(&mut self, arm: &ast::Arm) {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6648347..91b92d8 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -447,9 +447,6 @@
visitor.visit_pat(&field.pat)
}
}
- PatKind::Tuple(ref elems) => {
- walk_list!(visitor, visit_pat, elems);
- }
PatKind::Box(ref subpattern) |
PatKind::Ref(ref subpattern, _) |
PatKind::Paren(ref subpattern) => {
@@ -465,7 +462,9 @@
visitor.visit_expr(upper_bound);
}
PatKind::Wild | PatKind::Rest => {},
- PatKind::Slice(ref elems) => {
+ PatKind::Tuple(ref elems)
+ | PatKind::Slice(ref elems)
+ | PatKind::Or(ref elems) => {
walk_list!(visitor, visit_pat, elems);
}
PatKind::Mac(ref mac) => visitor.visit_mac(mac),
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index bed898f..0b8f16b 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -470,6 +470,7 @@
option_env,
opt_out_copy,
or,
+ or_patterns,
Ord,
Ordering,
Output,
diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.rs b/src/test/ui/feature-gate/feature-gate-or_patterns.rs
new file mode 100644
index 0000000..036a609
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-or_patterns.rs
@@ -0,0 +1,9 @@
+#![crate_type="lib"]
+
+pub fn example(x: Option<usize>) {
+ match x {
+ Some(0 | 1 | 2) => {}
+ //~^ ERROR: or-patterns syntax is experimental
+ _ => {}
+ }
+}
diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.stderr b/src/test/ui/feature-gate/feature-gate-or_patterns.stderr
new file mode 100644
index 0000000..aaabb54
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-or_patterns.stderr
@@ -0,0 +1,12 @@
+error[E0658]: or-patterns syntax is experimental
+ --> $DIR/feature-gate-or_patterns.rs:5:14
+ |
+LL | Some(0 | 1 | 2) => {}
+ | ^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/54883
+ = help: add `#![feature(or_patterns)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs
index 7b97218..f27caa5 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.rs
+++ b/src/test/ui/parser/pat-lt-bracket-6.rs
@@ -2,8 +2,9 @@
struct Test(&'static u8, [u8; 0]);
let x = Test(&0, []);
- let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
- //~^ ERROR subslice patterns are unstable
+ 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 201465b..6f08f0a 100644
--- a/src/test/ui/parser/pat-lt-bracket-6.stderr
+++ b/src/test/ui/parser/pat-lt-bracket-6.stderr
@@ -1,8 +1,8 @@
-error: expected one of `)`, `,`, or `@`, found `[`
+error: expected one of `)`, `,`, `@`, or `|`, found `[`
--> $DIR/pat-lt-bracket-6.rs:5:19
|
LL | let Test(&desc[..]) = x;
- | ^ expected one of `)`, `,`, or `@` here
+ | ^ expected one of `)`, `,`, `@`, or `|` here
error[E0658]: subslice patterns are unstable
--> $DIR/pat-lt-bracket-6.rs:5:20
@@ -14,7 +14,7 @@
= help: add `#![feature(slice_patterns)]` to the crate attributes to enable
error[E0308]: mismatched types
- --> $DIR/pat-lt-bracket-6.rs:9:30
+ --> $DIR/pat-lt-bracket-6.rs:10:30
|
LL | const RECOVERY_WITNESS: () = 0;
| ^ expected (), found integer
diff --git a/src/test/ui/parser/pat-lt-bracket-7.rs b/src/test/ui/parser/pat-lt-bracket-7.rs
index 020fdb8..327aef5 100644
--- a/src/test/ui/parser/pat-lt-bracket-7.rs
+++ b/src/test/ui/parser/pat-lt-bracket-7.rs
@@ -2,7 +2,8 @@
struct Thing(u8, [u8; 0]);
let foo = core::iter::empty();
- for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
+ for Thing(x[]) in foo {}
+ //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
}
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr
index 17557ef..196f1c0 100644
--- a/src/test/ui/parser/pat-lt-bracket-7.stderr
+++ b/src/test/ui/parser/pat-lt-bracket-7.stderr
@@ -1,11 +1,11 @@
-error: expected one of `)`, `,`, or `@`, found `[`
+error: expected one of `)`, `,`, `@`, or `|`, found `[`
--> $DIR/pat-lt-bracket-7.rs:5:16
|
LL | for Thing(x[]) in foo {}
- | ^ expected one of `)`, `,`, or `@` here
+ | ^ expected one of `)`, `,`, `@`, or `|` here
error[E0308]: mismatched types
- --> $DIR/pat-lt-bracket-7.rs:8:30
+ --> $DIR/pat-lt-bracket-7.rs:9:30
|
LL | const RECOVERY_WITNESS: () = 0;
| ^ expected (), found integer
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
index e6c59fc..c6be2c9 100644
--- a/src/test/ui/parser/recover-for-loop-parens-around-head.rs
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
@@ -8,7 +8,7 @@
let vec = vec![1, 2, 3];
for ( elem in vec ) {
- //~^ ERROR expected one of `)`, `,`, or `@`, found `in`
+ //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found `in`
//~| ERROR unexpected closing `)`
const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
}
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
index c160e64..1b5b6cc 100644
--- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
@@ -1,8 +1,8 @@
-error: expected one of `)`, `,`, or `@`, found `in`
+error: expected one of `)`, `,`, `@`, or `|`, found `in`
--> $DIR/recover-for-loop-parens-around-head.rs:10:16
|
LL | for ( elem in vec ) {
- | ^^ expected one of `)`, `,`, or `@` here
+ | ^^ expected one of `)`, `,`, `@`, or `|` here
error: unexpected closing `)`
--> $DIR/recover-for-loop-parens-around-head.rs:10:23