diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 7ada56cfa7611..0dad2dda837b5 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -140,6 +140,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { 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 99fe9f1682f16..2c6373bdfa40d 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -709,6 +709,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { 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 0f6e834ca26df..d2ea485b5db82 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2669,6 +2669,9 @@ impl<'a> LoweringContext<'a> { 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 57fd0be77ecff..2ae08568b7f7d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -882,6 +882,7 @@ impl Pat { 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) } @@ -976,6 +977,9 @@ pub enum PatKind { /// `0 <= position <= subpats.len()` TupleStruct(QPath, HirVec
>, Option >),
+
/// 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 2fd683ed83c54..157b7c07a9b38 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -4,7 +4,7 @@ use syntax::source_map::{SourceMap, Spanned};
use syntax::parse::ParseSess;
use syntax::print::pp::{self, Breaks};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
-use syntax::print::pprust::{self, Comments, PrintState};
+use syntax::print::pprust::{self, Comments, PrintState, SeparatorSpacing};
use syntax::symbol::kw;
use syntax::util::parser::{self, AssocOp, Fixity};
use syntax_pos::{self, BytePos, FileName};
@@ -1687,6 +1687,10 @@ impl<'a> State<'a> {
self.s.space();
self.s.word("}");
}
+ PatKind::Or(ref pats) => {
+ let spacing = SeparatorSpacing::Both;
+ self.strsep("|", spacing, 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 a55803e255bf6..73ca981bbe868 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1290,6 +1290,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
+ 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 d72b0addae915..0dec7ef4f0061 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -657,6 +657,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
}
}
+ PatternKind::Or { ref pats } => {
+ // FIXME(#47184): extract or handle `pattern_user_ty` somehow
+ 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 3473155a3ea3e..8d049b53988a9 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -195,6 +195,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
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 65e92d422b022..ec85daccd476e 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -87,6 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatternKind::AscribeUserType { .. } |
PatternKind::Array { .. } |
PatternKind::Wild |
+ PatternKind::Or { .. } |
PatternKind::Binding { .. } |
PatternKind::Leaf { .. } |
PatternKind::Deref { .. } => {
@@ -130,6 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
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 1833ee30624bb..ae59244d37f51 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -75,9 +75,6 @@
/// D((r_1, p_(i,2), .., p_(i,n)))
/// D((r_2, p_(i,2), .., p_(i,n)))
///
-/// Note that the OR-patterns are not always used directly in Rust, but are used to derive
-/// the exhaustive integer matching rules, so they're written here for posterity.
-///
/// The algorithm for computing `U`
/// -------------------------------
/// The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
@@ -1359,6 +1356,9 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
Some(vec![Slice(pat_len)])
}
}
+ PatternKind::Or { .. } => {
+ bug!("support for or-patterns has not been fully implemented yet.");
+ }
}
}
@@ -1884,6 +1884,10 @@ fn specialize<'p, 'a: 'p, 'tcx>(
"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 bebb0719af808..d2a5793e70363 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -175,6 +175,11 @@ pub enum PatternKind<'tcx> {
slice: Option >),
+ /// An or-pattern `A | B | C`.
+ Or(Vec >),
+
/// A possibly qualified path pattern.
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
/// or associated constants. Qualified path patterns `::B::C`/`::B::C` can
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index acafe327640d0..b67b4619d7f21 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1050,7 +1050,6 @@ pub fn noop_visit_pat