about summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-03-27 09:33:02 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2025-03-28 09:18:57 +1100
commit9f089e080c47bc282aa98f1e8c72ff44076afbb9 (patch)
tree89a9f31ddae2fe6fa86404d891cce7a51d4d71d6 /compiler/rustc_ast_lowering
parent217693a1f02ca6431a434926ff3417bdb6dbac2e (diff)
downloadrust-9f089e080c47bc282aa98f1e8c72ff44076afbb9.tar.gz
rust-9f089e080c47bc282aa98f1e8c72ff44076afbb9.zip
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.
Diffstat (limited to 'compiler/rustc_ast_lowering')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs1
2 files changed, 3 insertions, 1 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ced9064fd9f..4041e5d092a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1495,6 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
         self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
+            PatKind::Missing => None,
             PatKind::Ident(_, ident, _) => {
                 if ident.name != kw::Empty {
                     Some(self.lower_ident(ident))
@@ -1506,7 +1507,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             _ => {
                 self.dcx().span_delayed_bug(
                     param.pat.span,
-                    "non-ident/wild param pat must trigger an error",
+                    "non-missing/ident/wild param pat must trigger an error",
                 );
                 None
             }
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 07cc64a1358..f94d788a9b0 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             let pat_hir_id = self.lower_node_id(pattern.id);
             let node = loop {
                 match &pattern.kind {
+                    PatKind::Missing => break hir::PatKind::Missing,
                     PatKind::Wild => break hir::PatKind::Wild,
                     PatKind::Never => break hir::PatKind::Never,
                     PatKind::Ident(binding_mode, ident, sub) => {