Exhaustively handle expressions in patterns
This commit is contained in:
parent
5df69191cb
commit
c9365dd09f
36 changed files with 447 additions and 197 deletions
|
@ -1519,6 +1519,26 @@ impl fmt::Debug for DotDotPos {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct PatExpr<'hir> {
|
||||
pub hir_id: HirId,
|
||||
pub span: Span,
|
||||
pub kind: PatExprKind<'hir>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum PatExprKind<'hir> {
|
||||
Lit {
|
||||
lit: &'hir Lit,
|
||||
// FIXME: move this into `Lit` and handle negated literal expressions
|
||||
// once instead of matching on unop neg expressions everywhere.
|
||||
negated: bool,
|
||||
},
|
||||
ConstBlock(ConstBlock),
|
||||
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
|
||||
Path(QPath<'hir>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum PatKind<'hir> {
|
||||
/// Represents a wildcard pattern (i.e., `_`).
|
||||
|
@ -1564,13 +1584,13 @@ pub enum PatKind<'hir> {
|
|||
Ref(&'hir Pat<'hir>, Mutability),
|
||||
|
||||
/// A literal.
|
||||
Lit(&'hir Expr<'hir>),
|
||||
Lit(&'hir PatExpr<'hir>),
|
||||
|
||||
/// A guard pattern (e.g., `x if guard(x)`).
|
||||
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
|
||||
|
||||
/// A range pattern (e.g., `1..=2` or `1..2`).
|
||||
Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
|
||||
Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd),
|
||||
|
||||
/// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
|
||||
///
|
||||
|
@ -4144,6 +4164,10 @@ pub enum Node<'hir> {
|
|||
OpaqueTy(&'hir OpaqueTy<'hir>),
|
||||
Pat(&'hir Pat<'hir>),
|
||||
PatField(&'hir PatField<'hir>),
|
||||
/// Needed as its own node with its own HirId for tracking
|
||||
/// the unadjusted type of literals within patterns
|
||||
/// (e.g. byte str literals not being of slice type).
|
||||
PatExpr(&'hir PatExpr<'hir>),
|
||||
Arm(&'hir Arm<'hir>),
|
||||
Block(&'hir Block<'hir>),
|
||||
LetStmt(&'hir LetStmt<'hir>),
|
||||
|
@ -4200,6 +4224,7 @@ impl<'hir> Node<'hir> {
|
|||
| Node::Block(..)
|
||||
| Node::Ctor(..)
|
||||
| Node::Pat(..)
|
||||
| Node::PatExpr(..)
|
||||
| Node::Arm(..)
|
||||
| Node::LetStmt(..)
|
||||
| Node::Crate(..)
|
||||
|
|
|
@ -342,6 +342,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
|
||||
walk_pat_field(self, f)
|
||||
}
|
||||
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
|
||||
walk_pat_expr(self, expr)
|
||||
}
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
||||
walk_anon_const(self, c)
|
||||
}
|
||||
|
@ -685,10 +688,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
|
|||
try_visit!(visitor.visit_ident(ident));
|
||||
visit_opt!(visitor, visit_pat, optional_subpattern);
|
||||
}
|
||||
PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
|
||||
PatKind::Lit(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
|
||||
PatKind::Range(ref lower_bound, ref upper_bound, _) => {
|
||||
visit_opt!(visitor, visit_expr, lower_bound);
|
||||
visit_opt!(visitor, visit_expr, upper_bound);
|
||||
visit_opt!(visitor, visit_pat_expr, lower_bound);
|
||||
visit_opt!(visitor, visit_pat_expr, upper_bound);
|
||||
}
|
||||
PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
|
||||
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
|
||||
|
@ -710,6 +713,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
|
|||
visitor.visit_pat(field.pat)
|
||||
}
|
||||
|
||||
pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
|
||||
try_visit!(visitor.visit_id(expr.hir_id));
|
||||
match &expr.kind {
|
||||
PatExprKind::Lit { .. } => V::Result::output(),
|
||||
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
|
||||
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
|
||||
try_visit!(visitor.visit_id(constant.hir_id));
|
||||
visitor.visit_nested_body(constant.body)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue