Skip to content

Commit 32f3301

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 aba76d0 commit 32f3301

File tree

8 files changed

+8
-0
lines changed

8 files changed

+8
-0
lines changed

clippy_lints/src/equatable_if_let.rs

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
4545
pats.iter().all(unary_pattern)
4646
}
4747
match &pat.kind {
48+
PatKind::Missing => unreachable!(),
4849
PatKind::Slice(_, _, _)
4950
| PatKind::Range(_, _, _)
5051
| PatKind::Binding(..)

clippy_lints/src/matches/match_same_arms.rs

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>(
253253
impl<'a> NormalizedPat<'a> {
254254
fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self {
255255
match pat.kind {
256+
PatKind::Missing => unreachable!(),
256257
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
257258
PatKind::Binding(.., Some(pat))
258259
| PatKind::Box(pat)

clippy_lints/src/matches/single_match.rs

+1
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ impl<'a> PatState<'a> {
406406
pats.iter().map(|p| p.pat),
407407
),
408408

409+
PatKind::Missing => unreachable!(),
409410
PatKind::Wild
410411
| PatKind::Binding(_, _, _, None)
411412
| PatKind::Expr(_)

clippy_lints/src/unnested_or_patterns.rs

+1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
224224

225225
// We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`.
226226
let changed = match &mut focus_kind {
227+
Missing => unreachable!(),
227228
// These pattern forms are "leafs" and do not have sub-patterns.
228229
// Therefore they are not some form of constructor `C`,
229230
// with which a pattern `C(p_0)` may be formed,

clippy_lints/src/utils/author.rs

+1
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
676676
}
677677

678678
match pat.value.kind {
679+
PatKind::Missing => unreachable!(),
679680
PatKind::Wild => kind!("Wild"),
680681
PatKind::Never => kind!("Never"),
681682
PatKind::Binding(ann, _, name, sub) => {

clippy_utils/src/ast_utils/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool {
3333
pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
3434
use PatKind::*;
3535
match (&l.kind, &r.kind) {
36+
(Missing, _) | (_, Missing) => unreachable!(),
3637
(Paren(l), _) => eq_pat(l, r),
3738
(_, Paren(r)) => eq_pat(l, r),
3839
(Wild, Wild) | (Rest, Rest) => true,

clippy_utils/src/hir_utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
11241124
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
11251125
std::mem::discriminant(&pat.kind).hash(&mut self.s);
11261126
match pat.kind {
1127+
PatKind::Missing => unreachable!(),
11271128
PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => {
11281129
std::mem::discriminant(&by_ref).hash(&mut self.s);
11291130
std::mem::discriminant(&mutability).hash(&mut self.s);

clippy_utils/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
18571857
}
18581858

18591859
match pat.kind {
1860+
PatKind::Missing => unreachable!(),
18601861
PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
18611862
PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
18621863
PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),

0 commit comments

Comments
 (0)