Skip to content

Commit 9f089e0

Browse files
committed
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.
1 parent 217693a commit 9f089e0

File tree

40 files changed

+86
-46
lines changed

40 files changed

+86
-46
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ impl Pat {
563563
/// This is intended for use by diagnostics.
564564
pub fn to_ty(&self) -> Option<P<Ty>> {
565565
let kind = match &self.kind {
566+
PatKind::Missing => unreachable!(),
566567
// In a type expression `_` is an inference variable.
567568
PatKind::Wild => TyKind::Infer,
568569
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
@@ -625,7 +626,8 @@ impl Pat {
625626
| PatKind::Guard(s, _) => s.walk(it),
626627

627628
// These patterns do not contain subpatterns, skip.
628-
PatKind::Wild
629+
PatKind::Missing
630+
| PatKind::Wild
629631
| PatKind::Rest
630632
| PatKind::Never
631633
| PatKind::Expr(_)
@@ -676,6 +678,7 @@ impl Pat {
676678
/// Return a name suitable for diagnostics.
677679
pub fn descr(&self) -> Option<String> {
678680
match &self.kind {
681+
PatKind::Missing => unreachable!(),
679682
PatKind::Wild => Some("_".to_string()),
680683
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
681684
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
@@ -769,6 +772,9 @@ pub enum RangeSyntax {
769772
// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
770773
#[derive(Clone, Encodable, Decodable, Debug)]
771774
pub enum PatKind {
775+
/// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
776+
Missing,
777+
772778
/// Represents a wildcard pattern (`_`).
773779
Wild,
774780

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,7 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
15721572
vis.visit_id(id);
15731573
match kind {
15741574
PatKind::Err(_guar) => {}
1575-
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
1575+
PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
15761576
PatKind::Ident(_binding_mode, ident, sub) => {
15771577
vis.visit_ident(ident);
15781578
visit_opt(sub, |sub| vis.visit_pat(sub));

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
727727
try_visit!(visitor.visit_pat(subpattern));
728728
try_visit!(visitor.visit_expr(guard_condition));
729729
}
730-
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
730+
PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
731731
PatKind::Err(_guar) => {}
732732
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
733733
walk_list!(visitor, visit_pat, elems);

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14951495

14961496
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
14971497
self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
1498+
PatKind::Missing => None,
14981499
PatKind::Ident(_, ident, _) => {
14991500
if ident.name != kw::Empty {
15001501
Some(self.lower_ident(ident))
@@ -1506,7 +1507,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15061507
_ => {
15071508
self.dcx().span_delayed_bug(
15081509
param.pat.span,
1509-
"non-ident/wild param pat must trigger an error",
1510+
"non-missing/ident/wild param pat must trigger an error",
15101511
);
15111512
None
15121513
}

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2626
let pat_hir_id = self.lower_node_id(pattern.id);
2727
let node = loop {
2828
match &pattern.kind {
29+
PatKind::Missing => break hir::PatKind::Missing,
2930
PatKind::Wild => break hir::PatKind::Wild,
3031
PatKind::Never => break hir::PatKind::Never,
3132
PatKind::Ident(binding_mode, ident, sub) => {

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ impl<'a> AstValidator<'a> {
239239
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
240240
for Param { pat, .. } in &decl.inputs {
241241
match pat.kind {
242-
PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
242+
PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
243243
PatKind::Ident(BindingMode::MUT, ident, None) => {
244244
report_err(pat.span, Some(ident), true)
245245
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,9 +1622,9 @@ impl<'a> State<'a> {
16221622
fn print_pat(&mut self, pat: &ast::Pat) {
16231623
self.maybe_print_comment(pat.span.lo());
16241624
self.ann.pre(self, AnnNode::Pat(pat));
1625-
/* Pat isn't normalized, but the beauty of it
1626-
is that it doesn't matter */
1625+
/* Pat isn't normalized, but the beauty of it is that it doesn't matter */
16271626
match &pat.kind {
1627+
PatKind::Missing => unreachable!(),
16281628
PatKind::Wild => self.word("_"),
16291629
PatKind::Never => self.word("!"),
16301630
PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => {
@@ -1946,12 +1946,7 @@ impl<'a> State<'a> {
19461946
if let Some(eself) = input.to_self() {
19471947
self.print_explicit_self(&eself);
19481948
} else {
1949-
let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
1950-
ident.name == kw::Empty
1951-
} else {
1952-
false
1953-
};
1954-
if !invalid {
1949+
if !matches!(input.pat.kind, PatKind::Missing) {
19551950
self.print_pat(&input.pat);
19561951
self.word(":");
19571952
self.space();

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,7 @@ impl<'hir> Pat<'hir> {
15161516

15171517
use PatKind::*;
15181518
match self.kind {
1519+
Missing => unreachable!(),
15191520
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
15201521
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
15211522
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
@@ -1543,7 +1544,7 @@ impl<'hir> Pat<'hir> {
15431544

15441545
use PatKind::*;
15451546
match self.kind {
1546-
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
1547+
Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
15471548
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
15481549
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
15491550
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@@ -1681,6 +1682,9 @@ pub enum TyPatKind<'hir> {
16811682

16821683
#[derive(Debug, Clone, Copy, HashStable_Generic)]
16831684
pub enum PatKind<'hir> {
1685+
/// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
1686+
Missing,
1687+
16841688
/// Represents a wildcard pattern (i.e., `_`).
16851689
Wild,
16861690

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
744744
visit_opt!(visitor, visit_pat_expr, lower_bound);
745745
visit_opt!(visitor, visit_pat_expr, upper_bound);
746746
}
747-
PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
747+
PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
748748
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
749749
walk_list!(visitor, visit_pat, prepatterns);
750750
visit_opt!(visitor, visit_pat, slice_pattern);

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ fn resolve_local<'tcx>(
701701

702702
PatKind::Ref(_, _)
703703
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
704+
| PatKind::Missing
704705
| PatKind::Wild
705706
| PatKind::Never
706707
| PatKind::Expr(_)

0 commit comments

Comments
 (0)