diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 064f05ef1f3e..944ae65ffc67 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -563,6 +563,7 @@ impl Pat {
/// This is intended for use by diagnostics.
pub fn to_ty(&self) -> Option
> {
let kind = match &self.kind {
+ PatKind::Missing => unreachable!(),
// In a type expression `_` is an inference variable.
PatKind::Wild => TyKind::Infer,
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
@@ -625,7 +626,8 @@ pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) {
| PatKind::Guard(s, _) => s.walk(it),
// These patterns do not contain subpatterns, skip.
- PatKind::Wild
+ PatKind::Missing
+ | PatKind::Wild
| PatKind::Rest
| PatKind::Never
| PatKind::Expr(_)
@@ -676,6 +678,7 @@ pub fn contains_never_pattern(&self) -> bool {
/// Return a name suitable for diagnostics.
pub fn descr(&self) -> Option {
match &self.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild => Some("_".to_string()),
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
@@ -769,6 +772,9 @@ pub enum RangeSyntax {
// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PatKind {
+ /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.
+ Missing,
+
/// Represents a wildcard pattern (`_`).
Wild,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 274fe312f7fa..8c6ddf2a69c9 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1572,7 +1572,7 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) {
vis.visit_id(id);
match kind {
PatKind::Err(_guar) => {}
- PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+ PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
PatKind::Ident(_binding_mode, ident, sub) => {
vis.visit_ident(ident);
visit_opt(sub, |sub| vis.visit_pat(sub));
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 2716601ca4f9..3d78f65f634b 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -727,7 +727,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
try_visit!(visitor.visit_pat(subpattern));
try_visit!(visitor.visit_expr(guard_condition));
}
- PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+ PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
PatKind::Err(_guar) => {}
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
walk_list!(visitor, visit_pat, elems);
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ced9064fd9f4..4041e5d092aa 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1495,6 +1495,7 @@ fn lower_precise_capturing_args(
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] {
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 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] {
_ => {
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 07cc64a1358e..f94d788a9b0e 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -26,6 +26,7 @@ fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'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) => {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index a1487ca74be8..ab6d4644f7e9 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -239,7 +239,7 @@ fn visibility_not_permitted(&self, vis: &Visibility, note: errors::VisibilityNot
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) {
for Param { pat, .. } in &decl.inputs {
match pat.kind {
- PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
+ PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
PatKind::Ident(BindingMode::MUT, ident, None) => {
report_err(pat.span, Some(ident), true)
}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index cdb181794498..f9e17fb0539d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1622,9 +1622,9 @@ fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_pa
fn print_pat(&mut self, pat: &ast::Pat) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));
- /* Pat isn't normalized, but the beauty of it
- is that it doesn't matter */
+ /* Pat isn't normalized, but the beauty of it is that it doesn't matter */
match &pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild => self.word("_"),
PatKind::Never => self.word("!"),
PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => {
@@ -1946,12 +1946,7 @@ fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
if let Some(eself) = input.to_self() {
self.print_explicit_self(&eself);
} else {
- let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
- ident.name == kw::Empty
- } else {
- false
- };
- if !invalid {
+ if !matches!(input.pat.kind, PatKind::Missing) {
self.print_pat(&input.pat);
self.word(":");
self.space();
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 751c379b21a6..08e37accb8a3 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1516,6 +1516,7 @@ fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
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 @@ fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
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,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 506358341b50..ea3f396761b1 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
visit_opt!(visitor, visit_pat_expr, lower_bound);
visit_opt!(visitor, visit_pat_expr, upper_bound);
}
- PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
+ PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
walk_list!(visitor, visit_pat, prepatterns);
visit_opt!(visitor, visit_pat, slice_pattern);
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 255f5fee52a8..d63fef8c0ef2 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -701,6 +701,7 @@ fn is_binding_pat(pat: &hir::Pat<'_>) -> bool {
PatKind::Ref(_, _)
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
+ | PatKind::Missing
| PatKind::Wild
| PatKind::Never
| PatKind::Expr(_)
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index ddaca89ccf82..a4961fc2c850 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1875,6 +1875,7 @@ fn print_pat(&mut self, pat: &hir::Pat<'_>) {
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
match pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild => self.word("_"),
PatKind::Never => self.word("!"),
PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index a75f6f4caac9..0ed03a03c1b4 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -482,7 +482,8 @@ pub(super) fn pat_guaranteed_to_constitute_read_for_never(&self, pat: &hir::Pat<
// All of these constitute a read, or match on something that isn't `!`,
// which would require a `NeverToAny` coercion.
- hir::PatKind::Binding(_, _, _, _)
+ hir::PatKind::Missing
+ | hir::PatKind::Binding(_, _, _, _)
| hir::PatKind::Struct(_, _, _)
| hir::PatKind::TupleStruct(_, _, _)
| hir::PatKind::Tuple(_, _)
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c71a5ea8b976..d50f235ad4d1 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -611,6 +611,7 @@ fn maybe_read_scrutinee<'t>(
for pat in pats {
self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
match &pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Binding(.., opt_sub_pat) => {
// If the opt_sub_pat is None, then the binding does not count as
// a wildcard for the purpose of borrowing discr.
@@ -1884,6 +1885,7 @@ fn cat_pattern(
| PatKind::Expr(..)
| PatKind::Range(..)
| PatKind::Never
+ | PatKind::Missing
| PatKind::Wild
| PatKind::Err(_) => {
// always ok
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index f1f956779c94..0d4ecbc867b7 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -341,7 +341,7 @@ fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<
};
let ty = match pat.kind {
- PatKind::Wild | PatKind::Err(_) => expected,
+ PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected,
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
@@ -505,9 +505,11 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> A
},
// Ref patterns are complicated, we handle them in `check_pat_ref`.
- PatKind::Ref(..) => AdjustMode::Pass,
+ PatKind::Ref(..)
+ // No need to do anything on a missing pattern.
+ | PatKind::Missing
// A `_` pattern works with any expected type, so there's no need to do anything.
- PatKind::Wild
+ | PatKind::Wild
// A malformed pattern doesn't have an expected type, so let's just accept any type.
| PatKind::Err(_)
// Bindings also work with whatever the expected type is,
@@ -1037,7 +1039,8 @@ fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
| PatKind::Tuple(..)
| PatKind::Slice(..) => "binding",
- PatKind::Wild
+ PatKind::Missing
+ | PatKind::Wild
| PatKind::Never
| PatKind::Binding(..)
| PatKind::Box(..)
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9dccd4a0552c..0b5cdf99de5a 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -778,21 +778,19 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
}
if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
for arg in sig.decl.inputs.iter() {
- if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
- if ident.name == kw::Empty {
- let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
+ if let ast::PatKind::Missing = arg.pat.kind {
+ let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
- let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
- (snip.as_str(), Applicability::MachineApplicable)
- } else {
- ("", Applicability::HasPlaceholders)
- };
- cx.emit_span_lint(
- ANONYMOUS_PARAMETERS,
- arg.pat.span,
- BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
- );
- }
+ let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
+ (snip.as_str(), Applicability::MachineApplicable)
+ } else {
+ ("", Applicability::HasPlaceholders)
+ };
+ cx.emit_span_lint(
+ ANONYMOUS_PARAMETERS,
+ arg.pat.span,
+ BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
+ );
}
}
}
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 7b43aac90c74..806bca78f787 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1201,7 +1201,8 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
// Do not lint on `(..)` as that will result in the other arms being useless.
Paren(_)
// The other cases do not contain sub-patterns.
- | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
+ | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None)
+ | Path(..) | Err(_) => {},
// These are list-like patterns; parens can always be removed.
TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
self.check_unused_parens_pat(cx, p, false, false, keep_space);
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 6783bbf8bf42..413717e45ebf 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 7d62ab7970d0..f3da2a5cc8e4 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(_)
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 29d400a957b4..11672163b658 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -118,7 +118,7 @@ pub(super) fn for_pattern(
let place = place_builder.try_to_place(cx);
let mut subpairs = Vec::new();
let test_case = match pattern.kind {
- PatKind::Wild | PatKind::Error(_) => None,
+ PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None,
PatKind::Or { ref pats } => Some(TestCase::Or {
pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 3acf2a6a2a61..977d4f3e931b 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -920,6 +920,7 @@ fn visit_primary_bindings_special(
PatKind::Constant { .. }
| PatKind::Range { .. }
+ | PatKind::Missing
| PatKind::Wild
| PatKind::Never
| PatKind::Error(_) => {}
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 7f2e7d5ca838..9572dfc52dac 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -313,6 +313,7 @@ fn visit_block(&mut self, block: &'a Block) {
fn visit_pat(&mut self, pat: &'a Pat<'tcx>) {
if self.in_union_destructure {
match pat.kind {
+ PatKind::Missing => unreachable!(),
// binding to a variable allows getting stuff out of variable
PatKind::Binding { .. }
// match is conditional on having this value
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 4bfeab44bf4b..f36a895849a1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -290,6 +290,8 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box PatKind::Missing,
+
hir::PatKind::Wild => PatKind::Wild,
hir::PatKind::Never => PatKind::Never,
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 16cef0ec3acb..ac71bb845a88 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -664,6 +664,7 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
print_indented!(self, "kind: PatKind {", depth_lvl);
match pat_kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild => {
print_indented!(self, "Wild", depth_lvl + 1);
}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index aad185783755..0f5d8d9fbedd 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2941,9 +2941,7 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
}
match ty {
Ok(ty) => {
- let ident = Ident::new(kw::Empty, this.prev_token.span);
- let bm = BindingMode::NONE;
- let pat = this.mk_pat_ident(ty.span, bm, ident);
+ let pat = this.mk_pat(ty.span, PatKind::Missing);
(pat, ty)
}
// If this is a C-variadic argument and we hit an error, return the error.
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 1278e98afcf6..718154481722 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -295,6 +295,7 @@ fn visit_pat(&mut self, p: &'v hir::Pat<'v>) {
record_variants!(
(self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind),
[
+ Missing,
Wild,
Binding,
Struct,
@@ -597,6 +598,7 @@ fn visit_pat(&mut self, p: &'v ast::Pat) {
record_variants!(
(self, p, p.kind, None, ast, Pat, PatKind),
[
+ Missing,
Wild,
Ident,
Struct,
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index a25a80cd45f7..e81527340524 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -457,7 +457,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
PatKind::AscribeUserType { subpattern, .. }
| PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern),
PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
- PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
+ PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
ctor = Wildcard;
fields = vec![];
arity = 0;
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index f81db58950cb..afcca81a485f 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -304,6 +304,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
Symbol::intern(&match &p.kind {
// FIXME(never_patterns): does this make sense?
+ PatKind::Missing => unreachable!(),
PatKind::Wild
| PatKind::Err(_)
| PatKind::Never
diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
index cd9ab2764ac4..3afb687040f4 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -45,6 +45,7 @@ fn array_rec(pats: &[Pat<'_>]) -> bool {
pats.iter().all(unary_pattern)
}
match &pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Slice(_, _, _)
| PatKind::Range(_, _, _)
| PatKind::Binding(..)
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 250f17fa9025..a21597ffb93d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -253,6 +253,7 @@ fn next(&mut self) -> Option {
impl<'a> NormalizedPat<'a> {
fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self {
match pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
PatKind::Binding(.., Some(pat))
| PatKind::Box(pat)
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 56fbd626eefc..836c46240ce7 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -406,6 +406,7 @@ fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
pats.iter().map(|p| p.pat),
),
+ PatKind::Missing => unreachable!(),
PatKind::Wild
| PatKind::Binding(_, _, _, None)
| PatKind::Expr(_)
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index f43715d6752e..8966e6851ac2 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us
// We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`.
let changed = match &mut focus_kind {
+ Missing => unreachable!(),
// These pattern forms are "leafs" and do not have sub-patterns.
// Therefore they are not some form of constructor `C`,
// with which a pattern `C(p_0)` may be formed,
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 4309cd2c9abd..b7dcd2ffb0ee 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -676,6 +676,7 @@ macro_rules! kind {
}
match pat.value.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild => kind!("Wild"),
PatKind::Never => kind!("Never"),
PatKind::Binding(ann, _, name, sub) => {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 6023ae9cc7b1..ed99f966d2b7 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool {
pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
use PatKind::*;
match (&l.kind, &r.kind) {
+ (Missing, _) | (_, Missing) => unreachable!(),
(Paren(l), _) => eq_pat(l, r),
(_, Paren(r)) => eq_pat(l, r),
(Wild, Wild) | (Rest, Rest) => true,
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 9938e64d2426..b813cd361ed8 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1124,6 +1124,7 @@ pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => {
std::mem::discriminant(&by_ref).hash(&mut self.s);
std::mem::discriminant(&mutability).hash(&mut self.s);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 1307ff79bc5d..bdcbe1437d0e 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1857,6 +1857,7 @@ fn are_refutable<'a, I: IntoIterator- >>(cx: &LateContext<'_>,
}
match pat.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 3fb3284e3d7f..81ff6327a4fc 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -2433,11 +2433,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param
}
pub(crate) fn is_named_param(param: &ast::Param) -> bool {
- if let ast::PatKind::Ident(_, ident, _) = param.pat.kind {
- ident.name != symbol::kw::Empty
- } else {
- true
- }
+ !matches!(param.pat.kind, ast::PatKind::Missing)
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index bafed41e39f4..8ec3de286dcb 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -42,6 +42,7 @@ pub(crate) fn is_short_pattern(
fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool {
match &pat.kind {
+ ast::PatKind::Missing => unreachable!(),
ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => {
true
}
@@ -100,6 +101,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option
fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
match self.kind {
+ PatKind::Missing => unreachable!(),
PatKind::Or(ref pats) => {
let pat_strs = pats
.iter()
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 40033f546d30..3490d3efc599 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -515,6 +515,8 @@ fn test_meta() {
#[test]
fn test_pat() {
+ // PatKind::Missing: untestable in isolation.
+
// PatKind::Wild
c1!(pat, [ _ ], "_");
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 31af323ecdab..4d1f12e34900 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -574,6 +574,11 @@ mod item_delegation_mac {
}
mod patterns {
+ /// PatKind::Missing
+ fn pat_missing() {
+ let _: fn(u32, T, &str);
+ }
+
/// PatKind::Wild
fn pat_wild() {
let _;
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 19ae66f7a07a..d8da941a3407 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -361,6 +361,7 @@ mod expressions {
+
{ builtin # offset_of(T, field) };
@@ -517,6 +518,8 @@ mod items {
}
}
mod patterns {
+ /// PatKind::Missing
+ fn pat_missing() { let _: fn(u32, T, &str); }
/// PatKind::Wild
fn pat_wild() { let _; }
/// PatKind::Ident