Skip to content

Commit 619fc1b

Browse files
committed
rustc_mir: match pair with or-pattern handling
Handle or-patterns when building MIR by expanding the MatchPair into n Candidates.
1 parent 95f437b commit 619fc1b

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

src/librustc_mir/build/matches/mod.rs

+39-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2020
use syntax::ast::Name;
2121
use syntax_pos::Span;
2222

23+
use std::mem;
24+
2325
// helper functions, broken out by category:
2426
mod simplify;
2527
mod test;
@@ -665,7 +667,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
665667
}
666668
}
667669

668-
#[derive(Debug)]
670+
#[derive(Clone, Debug)]
669671
pub struct Candidate<'pat, 'tcx> {
670672
// span of the original pattern that gave rise to this candidate
671673
span: Span,
@@ -883,7 +885,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
883885
}
884886

885887
// Test for the remaining candidates.
886-
self.test_candidates(
888+
self.test_candidates_with_or(
887889
span,
888890
unmatched_candidates,
889891
block,
@@ -1026,6 +1028,41 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10261028
}
10271029
}
10281030

1031+
fn test_candidates_with_or<'pat, 'b, 'c>(
1032+
&mut self,
1033+
span: Span,
1034+
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
1035+
block: BasicBlock,
1036+
otherwise_block: Option<BasicBlock>,
1037+
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>,
1038+
) {
1039+
let match_pair = &candidates.first().unwrap().match_pairs[0];
1040+
// FIXME(dlrobertson): This could use some cleaning up.
1041+
if let PatKind::Or { ref pats } = *match_pair.pattern.kind {
1042+
let match_pairs = mem::take(&mut candidates.first_mut().unwrap().match_pairs);
1043+
let mut new_candidates = pats.iter().map(|pat| {
1044+
let mut candidate = (*candidates.first().unwrap()).clone();
1045+
candidate.match_pairs = match_pairs.clone();
1046+
candidate.match_pairs[0].pattern = pat;
1047+
candidate
1048+
}).collect::<Vec<_>>();
1049+
let mut new_candidate_refs = new_candidates.iter_mut().collect::<Vec<_>>();
1050+
for candidate in candidates.iter_mut().skip(1) {
1051+
new_candidate_refs.push(candidate);
1052+
}
1053+
self.test_candidates(span, &mut *new_candidate_refs, block,
1054+
otherwise_block, fake_borrows);
1055+
for candidate in new_candidates.iter_mut() {
1056+
if !candidate.match_pairs.is_empty() {
1057+
candidate.match_pairs.remove(0);
1058+
}
1059+
}
1060+
} else {
1061+
self.test_candidates(span, candidates, block,
1062+
otherwise_block, fake_borrows)
1063+
}
1064+
}
1065+
10291066
/// This is the most subtle part of the matching algorithm. At
10301067
/// this point, the input candidates have been fully simplified,
10311068
/// and so we know that all remaining match-pairs require some

src/librustc_mir/hair/pattern/_match.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1480,8 +1480,14 @@ fn pat_constructors<'tcx>(
14801480
Some(vec![Slice(pat_len)])
14811481
}
14821482
}
1483-
PatKind::Or { .. } => {
1484-
bug!("support for or-patterns has not been fully implemented yet.");
1483+
PatKind::Or { ref pats } => {
1484+
let mut v = vec![];
1485+
for pat in pats {
1486+
if let Some(ctors) = pat_constructors(cx, pat, pcx) {
1487+
v.extend(ctors);
1488+
}
1489+
}
1490+
Some(v)
14851491
}
14861492
}
14871493
}
@@ -2053,8 +2059,14 @@ fn specialize<'p, 'a: 'p, 'tcx>(
20532059
}
20542060
}
20552061

2056-
PatKind::Or { .. } => {
2057-
bug!("support for or-patterns has not been fully implemented yet.");
2062+
PatKind::Or { ref pats } => {
2063+
let mut specialized_pats = vec![];
2064+
for pat in pats {
2065+
if let Some(s) = specialize(cx, &[pat], constructor, wild_patterns) {
2066+
specialized_pats.extend(s);
2067+
}
2068+
}
2069+
Some(SmallVec::from_vec(specialized_pats))
20582070
}
20592071
};
20602072
debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head);

0 commit comments

Comments
 (0)