From 9f089e080c47bc282aa98f1e8c72ff44076afbb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: 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>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- compiler/rustc_middle/src/thir.rs | 3 +++ compiler/rustc_middle/src/thir/visit.rs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_middle') diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf4..413717e45eb 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -747,6 +747,9 @@ pub struct Ascription<'tcx> { #[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 7d62ab7970d..f3da2a5cc8e 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -250,7 +250,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( mut callback: impl FnMut(&'a Pat<'tcx>), ) { match &pat.kind { - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Binding { subpattern: None, .. } | PatKind::Constant { value: _ } | PatKind::Range(_) -- cgit 1.4.1-3-g733a5