self.0.iter().map(|p| *p)
}
+ // If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
+ fn expand_or_pat(&self) -> Option<Vec<PatStack<'p, 'tcx>>> {
+ 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.0.extend_from_slice(&self.0[1..]);
+ new_patstack
+ })
+ .collect(),
+ )
+ } else {
+ None
+ }
+ }
+
/// This computes `D(self)`. See top of the file for explanations.
fn specialize_wildcard(&self) -> Option<Self> {
if self.head().is_wildcard() { Some(self.to_tail()) } else { None }
Matrix(vec![])
}
+ /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
pub fn push(&mut self, row: PatStack<'p, 'tcx>) {
- self.0.push(row)
+ if let Some(rows) = row.expand_or_pat() {
+ self.0.extend(rows);
+ } else {
+ self.0.push(row);
+ }
}
/// Iterate over the first component of each row
'a: 'q,
'p: 'q,
{
- Matrix(
- self.0
- .iter()
- .filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns))
- .collect(),
- )
+ self.0
+ .iter()
+ .filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns))
+ .collect()
}
}
where
T: IntoIterator<Item = PatStack<'p, 'tcx>>,
{
- Matrix(iter.into_iter().collect())
+ let mut matrix = Matrix::empty();
+ for x in iter {
+ // Using `push` ensures we correctly expand or-patterns.
+ matrix.push(x);
+ }
+ matrix
}
}
assert!(rows.iter().all(|r| r.len() == v.len()));
+ // If the first pattern is an or-pattern, expand it.
+ if let Some(vs) = v.expand_or_pat() {
+ return vs
+ .into_iter()
+ .map(|v| is_useful(cx, matrix, &v, witness_preference, hir_id))
+ .find(|result| result.is_useful())
+ .unwrap_or(NotUseful);
+ }
+
let (ty, span) = matrix
.heads()
.map(|r| (r.ty, r.span))
if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
Some(Slice(Slice { array_len, kind }))
}
- PatKind::Or { .. } => {
- bug!("support for or-patterns has not been fully implemented yet.");
- }
+ PatKind::Or { .. } => bug!(), // Should have been expanded earlier on.
}
}
_ => span_bug!(pat.span, "unexpected ctor {:?} for slice pat", constructor),
},
- PatKind::Or { .. } => {
- bug!("support for or-patterns has not been fully implemented yet.");
- }
+ PatKind::Or { .. } => bug!(), // Should have been expanded earlier on.
};
debug!("specialize({:#?}, {:#?}) = {:#?}", pat, ctor_wild_subpatterns, result);
--- /dev/null
+// should-ice
+#![allow(incomplete_features)]
+#![feature(or_patterns)]
+#![deny(unreachable_patterns)]
+
+// The ice will get removed once or-patterns are correctly implemented
+fn main() {
+ // We wrap patterns in a tuple because top-level or-patterns are special-cased for now.
+ match (0u8,) {
+ (1 | 2,) => {}
+ //~^ ERROR simplifyable pattern found
+ // This above is the ICE error message
+ _ => {}
+ }
+
+ match (0u8,) {
+ (1 | 2,) => {}
+ (1,) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match (0u8,) {
+ (1 | 2,) => {}
+ (2,) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match (0u8,) {
+ (1,) => {}
+ (2,) => {}
+ (1 | 2,) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match (0u8,) {
+ (1 | 1,) => {} // redundancy not detected for now
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (1 | 2, 3 | 4) => {}
+ (1, 2) => {}
+ (1, 3) => {} //~ ERROR unreachable pattern
+ (1, 4) => {} //~ ERROR unreachable pattern
+ (2, 4) => {} //~ ERROR unreachable pattern
+ (2 | 1, 4) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+}