Skip to content

Add new PatKind::Missing variants #139035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 7, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -563,6 +563,7 @@ impl Pat {
/// This is intended for use by diagnostics.
pub fn to_ty(&self) -> Option<P<Ty>> {
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 @@ impl Pat {
| 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 @@ impl Pat {
/// Return a name suitable for diagnostics.
pub fn descr(&self) -> Option<String> {
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,

2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -1572,7 +1572,7 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
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));
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 3 additions & 8 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1495,18 +1495,13 @@ 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::Ident(_, ident, _) => {
if ident.name != kw::Empty {
Some(self.lower_ident(ident))
} else {
None
}
}
PatKind::Missing => None,
PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)),
PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),
_ => {
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
}
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
@@ -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) => {
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -239,7 +239,7 @@ impl<'a> AstValidator<'a> {
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, 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)
}
11 changes: 3 additions & 8 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
@@ -1622,9 +1622,9 @@ impl<'a> State<'a> {
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 @@ impl<'a> State<'a> {
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();
6 changes: 5 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -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,

2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
@@ -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);
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
@@ -701,6 +701,7 @@ fn resolve_local<'tcx>(

PatKind::Ref(_, _)
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
| PatKind::Missing
| PatKind::Wild
| PatKind::Never
| PatKind::Expr(_)
1 change: 1 addition & 0 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1875,6 +1875,7 @@ impl<'a> State<'a> {
// 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) => {
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -482,7 +482,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// 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(_, _)
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -611,6 +611,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
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 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
| PatKind::Expr(..)
| PatKind::Range(..)
| PatKind::Never
| PatKind::Missing
| PatKind::Wild
| PatKind::Err(_) => {
// always ok
11 changes: 7 additions & 4 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
@@ -341,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},

// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Tuple(..)
| PatKind::Slice(..) => "binding",

PatKind::Wild
PatKind::Missing
| PatKind::Wild
| PatKind::Never
| PatKind::Binding(..)
| PatKind::Box(..)
26 changes: 12 additions & 14 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -778,21 +778,19 @@ impl EarlyLintPass for AnonymousParameters {
}
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 {
("<type>", 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 {
("<type>", Applicability::HasPlaceholders)
};
cx.emit_span_lint(
ANONYMOUS_PARAMETERS,
arg.pat.span,
BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
);
}
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
@@ -1201,7 +1201,8 @@ impl EarlyLintPass for UnusedParens {
// 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);
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
@@ -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,

3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
@@ -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(_)
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ impl<'tcx> MatchPairTree<'tcx> {
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(),
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
@@ -920,6 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

PatKind::Constant { .. }
| PatKind::Range { .. }
| PatKind::Missing
| PatKind::Wild
| PatKind::Never
| PatKind::Error(_) => {}
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
@@ -313,6 +313,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
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
2 changes: 2 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -290,6 +290,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let mut span = pat.span;

let kind = match pat.kind {
hir::PatKind::Missing => PatKind::Missing,

hir::PatKind::Wild => PatKind::Wild,

hir::PatKind::Never => PatKind::Never,
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/thir/print.rs
Original file line number Diff line number Diff line change
@@ -664,6 +664,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, "kind: PatKind {", depth_lvl);

match pat_kind {
PatKind::Missing => unreachable!(),
PatKind::Wild => {
print_indented!(self, "Wild", depth_lvl + 1);
}
4 changes: 1 addition & 3 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
@@ -2941,9 +2941,7 @@ impl<'a> Parser<'a> {
}
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.
2 changes: 2 additions & 0 deletions compiler/rustc_passes/src/input_stats.rs
Original file line number Diff line number Diff line change
@@ -295,6 +295,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
record_variants!(
(self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind),
[
Missing,
Wild,
Binding,
Struct,
@@ -597,6 +598,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
record_variants!(
(self, p, p.kind, None, ast, Pat, PatKind),
[
Missing,
Wild,
Ident,
Struct,
5 changes: 1 addition & 4 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
use rustc_session::lint;
use rustc_span::{BytePos, Span, Symbol, kw, sym};
use rustc_span::{BytePos, Span, Symbol, sym};
use tracing::{debug, instrument};

use self::LiveNodeKind::*;
@@ -1481,9 +1481,6 @@ impl<'tcx> Liveness<'_, 'tcx> {

fn should_warn(&self, var: Variable) -> Option<String> {
let name = self.ir.variable_name(var);
if name == kw::Empty {
return None;
}
let name = name.as_str();
if name.as_bytes()[0] == b'_' {
return None;
2 changes: 1 addition & 1 deletion compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
@@ -457,7 +457,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'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;
13 changes: 4 additions & 9 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
@@ -3999,22 +3999,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
self.report_error(ident.span, error(ident));
}

// Record as bound if it's valid:
let ident_valid = ident.name != kw::Empty;
if ident_valid {
bindings.last_mut().unwrap().1.insert(ident);
}
// Record as bound.
bindings.last_mut().unwrap().1.insert(ident);

if already_bound_or {
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
self.innermost_rib_bindings(ValueNS)[&ident]
} else {
// A completely fresh binding is added to the set.
let res = Res::Local(pat_id);
if ident_valid {
// A completely fresh binding add to the set if it's valid.
self.innermost_rib_bindings(ValueNS).insert(ident, res);
}
self.innermost_rib_bindings(ValueNS).insert(ident, res);
res
}
}
1 change: 1 addition & 0 deletions src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/equatable_if_let.rs
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
pats.iter().all(unary_pattern)
}
match &pat.kind {
PatKind::Missing => unreachable!(),
PatKind::Slice(_, _, _)
| PatKind::Range(_, _, _)
| PatKind::Binding(..)
Original file line number Diff line number Diff line change
@@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>(
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)
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/matches/single_match.rs
Original file line number Diff line number Diff line change
@@ -406,6 +406,7 @@ impl<'a> PatState<'a> {
pats.iter().map(|p| p.pat),
),

PatKind::Missing => unreachable!(),
PatKind::Wild
| PatKind::Binding(_, _, _, None)
| PatKind::Expr(_)
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
Original file line number Diff line number Diff line change
@@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, 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,
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/utils/author.rs
Original file line number Diff line number Diff line change
@@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}

match pat.value.kind {
PatKind::Missing => unreachable!(),
PatKind::Wild => kind!("Wild"),
PatKind::Never => kind!("Never"),
PatKind::Binding(ann, _, name, sub) => {
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/hir_utils.rs
Original file line number Diff line number Diff line change
@@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
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);
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
}

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),
6 changes: 1 addition & 5 deletions src/tools/rustfmt/src/items.rs
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 2 additions & 0 deletions src/tools/rustfmt/src/patterns.rs
Original file line number Diff line number Diff line change
@@ -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!(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you briefly explain how we know this is unreachable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gonna assume "no tests were hit" 😆

ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => {
true
}
@@ -100,6 +101,7 @@ impl Rewrite for Pat {

fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
match self.kind {
PatKind::Missing => unreachable!(),
PatKind::Or(ref pats) => {
let pat_strs = pats
.iter()
2 changes: 2 additions & 0 deletions tests/ui/macros/stringify.rs
Original file line number Diff line number Diff line change
@@ -515,6 +515,8 @@ fn test_meta() {

#[test]
fn test_pat() {
// PatKind::Missing: untestable in isolation.

// PatKind::Wild
c1!(pat, [ _ ], "_");

5 changes: 5 additions & 0 deletions tests/ui/unpretty/expanded-exhaustive.rs
Original file line number Diff line number Diff line change
@@ -574,6 +574,11 @@ mod items {
}

mod patterns {
/// PatKind::Missing
fn pat_missing() {
let _: fn(u32, T, &str);
}

/// PatKind::Wild
fn pat_wild() {
let _;
3 changes: 3 additions & 0 deletions tests/ui/unpretty/expanded-exhaustive.stdout
Original file line number Diff line number Diff line change
@@ -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