Factor or-pattern expansion
This commit is contained in:
parent
293af41790
commit
0162d603b3
@ -385,6 +385,27 @@ impl<'tcx> Pat<'tcx> {
|
||||
pub(super) fn is_wildcard(&self) -> bool {
|
||||
matches!(*self.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
|
||||
}
|
||||
|
||||
fn is_or_pat(&self) -> bool {
|
||||
matches!(*self.kind, PatKind::Or { .. })
|
||||
}
|
||||
|
||||
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
|
||||
fn expand_or_pat(&self) -> Vec<&Self> {
|
||||
fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
|
||||
if let PatKind::Or { pats } = pat.kind.as_ref() {
|
||||
for pat in pats {
|
||||
expand(pat, vec);
|
||||
}
|
||||
} else {
|
||||
vec.push(pat)
|
||||
}
|
||||
}
|
||||
|
||||
let mut pats = Vec::new();
|
||||
expand(self, &mut pats);
|
||||
pats
|
||||
}
|
||||
}
|
||||
|
||||
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
|
||||
@ -425,23 +446,14 @@ fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
|
||||
self.pats.iter().copied()
|
||||
}
|
||||
|
||||
// If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
|
||||
fn expand_or_pat(&self) -> Option<Vec<Self>> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else if let PatKind::Or { pats } = &*self.head().kind {
|
||||
Some(
|
||||
pats.iter()
|
||||
.map(|pat| {
|
||||
let mut new_patstack = PatStack::from_pattern(pat);
|
||||
new_patstack.pats.extend_from_slice(&self.pats[1..]);
|
||||
new_patstack
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// Recursively expand the first pattern into its subpatterns. Only useful if the pattern is an
|
||||
// or-pattern. Panics if `self` is empty.
|
||||
fn expand_or_pat<'a>(&'a self) -> impl Iterator<Item = PatStack<'p, 'tcx>> + Captures<'a> {
|
||||
self.head().expand_or_pat().into_iter().map(move |pat| {
|
||||
let mut new_patstack = PatStack::from_pattern(pat);
|
||||
new_patstack.pats.extend_from_slice(&self.pats[1..]);
|
||||
new_patstack
|
||||
})
|
||||
}
|
||||
|
||||
/// This computes `S(self.head_ctor(), self)`. See top of the file for explanations.
|
||||
@ -508,13 +520,12 @@ pub(super) fn column_count(&self) -> Option<usize> {
|
||||
self.patterns.get(0).map(|r| r.len())
|
||||
}
|
||||
|
||||
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
|
||||
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
|
||||
/// expands it.
|
||||
fn push(&mut self, row: PatStack<'p, 'tcx>) {
|
||||
if let Some(rows) = row.expand_or_pat() {
|
||||
for row in rows {
|
||||
// We recursively expand the or-patterns of the new rows.
|
||||
// This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`.
|
||||
self.push(row)
|
||||
if !row.is_empty() && row.head().is_or_pat() {
|
||||
for row in row.expand_or_pat() {
|
||||
self.patterns.push(row);
|
||||
}
|
||||
} else {
|
||||
self.patterns.push(row);
|
||||
@ -968,8 +979,9 @@ fn is_useful<'p, 'tcx>(
|
||||
let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
|
||||
|
||||
// If the first pattern is an or-pattern, expand it.
|
||||
let ret = if let Some(vs) = v.expand_or_pat() {
|
||||
let ret = if v.head().is_or_pat() {
|
||||
debug!("expanding or-pattern");
|
||||
let vs: Vec<_> = v.expand_or_pat().collect();
|
||||
let subspans: Vec<_> = vs.iter().map(|v| v.head().span).collect();
|
||||
// We expand the or pattern, trying each of its branches in turn and keeping careful track
|
||||
// of possible unreachable sub-branches.
|
||||
|
@ -53,8 +53,11 @@ fn main() {
|
||||
_ => {}
|
||||
}
|
||||
match 0 {
|
||||
// We get two errors because recursive or-pattern expansion means we don't notice the two
|
||||
// errors span a whole pattern. This could be better but doesn't matter much
|
||||
0 | (0 | 0) => {}
|
||||
//~^ ERROR unreachable
|
||||
//~| ERROR unreachable
|
||||
_ => {}
|
||||
}
|
||||
match None {
|
||||
|
@ -83,71 +83,77 @@ LL | (0 | 1) | 1 => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:56:14
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:14
|
||||
|
|
||||
LL | 0 | (0 | 0) => {}
|
||||
| ^^^^^
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:63:13
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:18
|
||||
|
|
||||
LL | 0 | (0 | 0) => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:13
|
||||
|
|
||||
LL | / Some(
|
||||
LL | | 0 | 0) => {}
|
||||
| |______________________^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:69:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:72:15
|
||||
|
|
||||
LL | | 0
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:71:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:74:15
|
||||
|
|
||||
LL | | 0] => {}
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:79:10
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:82:10
|
||||
|
|
||||
LL | [1
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:91:10
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:94:10
|
||||
|
|
||||
LL | [true
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:98:36
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:101:36
|
||||
|
|
||||
LL | (true | false, None | Some(true
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:114:14
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:117:14
|
||||
|
|
||||
LL | Some(0
|
||||
| ^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:133:19
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:136:19
|
||||
|
|
||||
LL | | false) => {}
|
||||
| ^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:141:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:144:15
|
||||
|
|
||||
LL | | true) => {}
|
||||
| ^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:147:15
|
||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:150:15
|
||||
|
|
||||
LL | | true,
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user