Add {ast,hir,thir}::PatKind::Missing variants.
"Missing" patterns are possible in bare fn types (`fn f(u32)`) and
similar places. Currently these are represented in the AST with
`ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no
sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for
HIR and THIR.
This is a bit nasty. It's very non-obvious, and easy to forget to check
for the exceptional empty identifier case.
This commit adds a new variant, `PatKind::Missing`, to do it properly.
The process I followed:
- Add a `Missing` variant to `{ast,hir,thir}::PatKind`.
- Chang `parse_param_general` to produce `ast::PatKind::Missing`
instead of `ast::PatKind::Missing`.
- Look through `kw::Empty` occurrences to find functions where an
existing empty ident check needs replacing with a `PatKind::Missing`
check: `print_param`, `check_trait_item`, `is_named_param`.
- Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive
match identified by the compiler.
- Find which arms are actually reachable by running the test suite,
changing them to something appropriate, usually by looking at what
would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no
`mut`, an empty ident, and no subpattern.
Quite a few of the `unreachable!()` arms were never reached. This makes
sense because `PatKind::Missing` can't happen in every pattern, only
in places like bare fn tys and trait fn decls.
I also tried an alternative approach: modifying `ast::Param::pat` to
hold an `Option<P<Pat>>` instead of a `P<Pat>`, but that quickly turned
into a very large and painful change. Adding `PatKind::Missing` is much
easier.
This commit is contained in:
@@ -1516,6 +1516,7 @@ impl<'hir> Pat<'hir> {
|
||||
|
||||
use PatKind::*;
|
||||
match self.kind {
|
||||
Missing => unreachable!(),
|
||||
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
|
||||
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
|
||||
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
|
||||
@@ -1543,7 +1544,7 @@ impl<'hir> Pat<'hir> {
|
||||
|
||||
use PatKind::*;
|
||||
match self.kind {
|
||||
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
|
||||
Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
|
||||
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
|
||||
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
|
||||
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
|
||||
@@ -1681,6 +1682,9 @@ pub enum TyPatKind<'hir> {
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum PatKind<'hir> {
|
||||
/// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
|
||||
Missing,
|
||||
|
||||
/// Represents a wildcard pattern (i.e., `_`).
|
||||
Wild,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user