Skip to content

Remove refs from Pat slices #87140

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 1 commit into from
Jul 16, 2021
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
19 changes: 14 additions & 5 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1067,6 +1067,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
eq_sign_span: Span,
assignments: &mut Vec<hir::Stmt<'hir>>,
) -> &'hir hir::Pat<'hir> {
self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments))
}

fn destructure_assign_mut(
&mut self,
lhs: &Expr,
eq_sign_span: Span,
assignments: &mut Vec<hir::Stmt<'hir>>,
) -> hir::Pat<'hir> {
match &lhs.kind {
// Underscore pattern.
ExprKind::Underscore => {
@@ -1080,7 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (before, after) = pats.split_at(i);
hir::PatKind::Slice(
before,
Some(self.pat_without_dbm(span, hir::PatKind::Wild)),
Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))),
after,
)
} else {
@@ -1165,14 +1174,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
let tuple_pat = hir::PatKind::Tuple(&[], Some(0));
return self.pat_without_dbm(lhs.span, tuple_pat);
} else {
return self.destructure_assign(e, eq_sign_span, assignments);
return self.destructure_assign_mut(e, eq_sign_span, assignments);
}
}
_ => {}
}
// Treat all other cases as normal lvalue.
let ident = Ident::new(sym::lhs, lhs.span);
let (pat, binding) = self.pat_ident(lhs.span, ident);
let (pat, binding) = self.pat_ident_mut(lhs.span, ident);
let ident = self.expr_ident(lhs.span, ident, binding);
let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, eq_sign_span);
let expr = self.expr(lhs.span, assign, ThinVec::new());
@@ -1191,7 +1200,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ctx: &str,
eq_sign_span: Span,
assignments: &mut Vec<hir::Stmt<'hir>>,
) -> (&'hir [&'hir hir::Pat<'hir>], Option<(usize, Span)>) {
) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) {
let mut rest = None;
let elements =
self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| {
@@ -1204,7 +1213,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
None
} else {
Some(self.destructure_assign(e, eq_sign_span, assignments))
Some(self.destructure_assign_mut(e, eq_sign_span, assignments))
}
}));
(elements, rest)
27 changes: 18 additions & 9 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2577,21 +2577,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
}

fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated)
}

fn pat_ident_binding_mode(
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (&'hir hir::Pat<'hir>, hir::HirId) {
let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
(self.arena.alloc(pat), hir_id)
}

fn pat_ident_binding_mode_mut(
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (hir::Pat<'hir>, hir::HirId) {
let hir_id = self.next_id();

(
self.arena.alloc(hir::Pat {
hir::Pat {
hir_id,
kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
span,
default_binding_modes: true,
}),
},
hir_id,
)
}
@@ -2609,13 +2623,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
}

fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
self.arena.alloc(hir::Pat {
hir_id: self.next_id(),
kind,
span,
default_binding_modes: false,
})
fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
hir::Pat { hir_id: self.next_id(), kind, span, default_binding_modes: false }
}

fn ty_path(
28 changes: 16 additions & 12 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,11 @@ use rustc_span::symbol::Ident;
use rustc_span::{source_map::Spanned, Span};

impl<'a, 'hir> LoweringContext<'a, 'hir> {
crate fn lower_pat(&mut self, mut pattern: &Pat) -> &'hir hir::Pat<'hir> {
crate fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
self.arena.alloc(self.lower_pat_mut(pattern))
}

crate fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
ensure_sufficient_stack(|| {
// loop here to avoid recursion
let node = loop {
@@ -34,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
PatKind::Or(ref pats) => {
break hir::PatKind::Or(
self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))),
self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))),
);
}
PatKind::Path(ref qself, ref path) => {
@@ -101,7 +105,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
pats: &[P<Pat>],
ctx: &str,
) -> (&'hir [&'hir hir::Pat<'hir>], Option<usize>) {
) -> (&'hir [hir::Pat<'hir>], Option<usize>) {
let mut elems = Vec::with_capacity(pats.len());
let mut rest = None;

@@ -140,7 +144,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

// It was not a sub-tuple pattern so lower it normally.
elems.push(self.lower_pat(pat));
elems.push(self.lower_pat_mut(pat));
}

for (_, pat) in iter {
@@ -149,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// ...but there was one again, so error.
self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
} else {
elems.push(self.lower_pat(pat));
elems.push(self.lower_pat_mut(pat));
}
}

@@ -189,11 +193,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
prev_rest_span = Some(sub.span);
slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub)));
break;
}
// It was not a subslice pattern so lower it normally.
_ => before.push(self.lower_pat(pat)),
_ => before.push(self.lower_pat_mut(pat)),
}
}

@@ -214,7 +218,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
} else {
// Lower the pattern normally.
after.push(self.lower_pat(pat));
after.push(self.lower_pat_mut(pat));
}
}

@@ -268,17 +272,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
self.pat_with_node_id_of(p, hir::PatKind::Wild)
self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild))
}

/// Construct a `Pat` with the `HirId` of `p.id` lowered.
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
self.arena.alloc(hir::Pat {
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
hir::Pat {
hir_id: self.lower_node_id(p.id),
kind,
span: p.span,
default_binding_modes: true,
})
}
}

/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
16 changes: 8 additions & 8 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -808,13 +808,13 @@ impl<'hir> Pat<'hir> {
}

use PatKind::*;
match &self.kind {
match self.kind {
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
Slice(before, slice, after) => {
before.iter().chain(slice.iter()).chain(after.iter()).all(|p| p.walk_short_(it))
before.iter().chain(slice).chain(after.iter()).all(|p| p.walk_short_(it))
}
}
}
@@ -836,13 +836,13 @@ impl<'hir> Pat<'hir> {
}

use PatKind::*;
match &self.kind {
match self.kind {
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
Box(s) | Ref(s, _) | Binding(.., Some(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)),
Slice(before, slice, after) => {
before.iter().chain(slice.iter()).chain(after.iter()).for_each(|p| p.walk_(it))
before.iter().chain(slice).chain(after.iter()).for_each(|p| p.walk_(it))
}
}
}
@@ -940,19 +940,19 @@ pub enum PatKind<'hir> {
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// `0 <= position <= subpats.len()`
TupleStruct(QPath<'hir>, &'hir [&'hir Pat<'hir>], Option<usize>),
TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], Option<usize>),

/// An or-pattern `A | B | C`.
/// Invariant: `pats.len() >= 2`.
Or(&'hir [&'hir Pat<'hir>]),
Or(&'hir [Pat<'hir>]),

/// A path pattern for an unit struct/variant or a (maybe-associated) constant.
Path(QPath<'hir>),

/// A tuple pattern (e.g., `(a, b)`).
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// `0 <= position <= subpats.len()`
Tuple(&'hir [&'hir Pat<'hir>], Option<usize>),
Tuple(&'hir [Pat<'hir>], Option<usize>),

/// A `box` pattern.
Box(&'hir Pat<'hir>),
@@ -975,7 +975,7 @@ pub enum PatKind<'hir> {
/// ```
/// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
/// ```
Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
}

#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
8 changes: 4 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -325,7 +325,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {

fn lower_tuple_subpats(
&mut self,
pats: &'tcx [&'tcx hir::Pat<'tcx>],
pats: &'tcx [hir::Pat<'tcx>],
expected_len: usize,
gap_pos: Option<usize>,
) -> Vec<FieldPat<'tcx>> {
@@ -338,7 +338,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.collect()
}

fn lower_patterns(&mut self, pats: &'tcx [&'tcx hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
pats.iter().map(|p| self.lower_pattern(p)).collect()
}

@@ -350,9 +350,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
&mut self,
span: Span,
ty: Ty<'tcx>,
prefix: &'tcx [&'tcx hir::Pat<'tcx>],
prefix: &'tcx [hir::Pat<'tcx>],
slice: &'tcx Option<&'tcx hir::Pat<'tcx>>,
suffix: &'tcx [&'tcx hir::Pat<'tcx>],
suffix: &'tcx [hir::Pat<'tcx>],
) -> PatKind<'tcx> {
let prefix = self.lower_patterns(prefix);
let slice = self.lower_opt_pattern(slice);
10 changes: 5 additions & 5 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
@@ -864,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
pat: &'tcx Pat<'tcx>,
qpath: &'tcx hir::QPath<'tcx>,
subpats: &'tcx [&'tcx Pat<'tcx>],
subpats: &'tcx [Pat<'tcx>],
ddpos: Option<usize>,
expected: Ty<'tcx>,
def_bm: BindingMode,
@@ -982,7 +982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_span: Span,
res: Res,
qpath: &hir::QPath<'_>,
subpats: &'tcx [&'tcx Pat<'tcx>],
subpats: &'tcx [Pat<'tcx>],
fields: &'tcx [ty::FieldDef],
expected: Ty<'tcx>,
had_err: bool,
@@ -1112,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_tuple(
&self,
span: Span,
elements: &'tcx [&'tcx Pat<'tcx>],
elements: &'tcx [Pat<'tcx>],
ddpos: Option<usize>,
expected: Ty<'tcx>,
def_bm: BindingMode,
@@ -1746,9 +1746,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_slice(
&self,
span: Span,
before: &'tcx [&'tcx Pat<'tcx>],
before: &'tcx [Pat<'tcx>],
slice: Option<&'tcx Pat<'tcx>>,
after: &'tcx [&'tcx Pat<'tcx>],
after: &'tcx [Pat<'tcx>],
expected: Ty<'tcx>,
def_bm: BindingMode,
ti: TopInfo<'tcx>,
17 changes: 6 additions & 11 deletions src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
@@ -260,17 +260,12 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
PatKind::Binding(_, _, ident, _) => return ident.name,
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
PatKind::Or(ref pats) => pats
.iter()
.map(|p| name_from_pat(&**p).to_string())
.collect::<Vec<String>>()
.join(" | "),
PatKind::Or(ref pats) => {
pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
}
PatKind::Tuple(ref elts, _) => format!(
"({})",
elts.iter()
.map(|p| name_from_pat(&**p).to_string())
.collect::<Vec<String>>()
.join(", ")
elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ")
),
PatKind::Box(ref p) => return name_from_pat(&**p),
PatKind::Ref(ref p, _) => return name_from_pat(&**p),
@@ -282,9 +277,9 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
}
PatKind::Range(..) => return kw::Underscore,
PatKind::Slice(ref begin, ref mid, ref end) => {
let begin = begin.iter().map(|p| name_from_pat(&**p).to_string());
let begin = begin.iter().map(|p| name_from_pat(p).to_string());
let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
let end = end.iter().map(|p| name_from_pat(&**p).to_string());
let end = end.iter().map(|p| name_from_pat(p).to_string());
format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
}
})
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
Original file line number Diff line number Diff line change
@@ -61,13 +61,13 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
match arm.pat.kind {
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
PatKind::TupleStruct(ref qpath, &[pat], _) =>
PatKind::TupleStruct(ref qpath, [pat], _) =>
matches!(pat.kind, PatKind::Wild) && is_lang_ctor(cx, qpath, ResultErr),
_ => false,
}
});
let unwrap_arm = &arms[1 - idx];
if let PatKind::TupleStruct(ref qpath, &[unwrap_pat], _) = unwrap_arm.pat.kind;
if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
if path_to_local_id(unwrap_arm.body, binding_hir_id);
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
@@ -625,7 +625,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
if let PatKind::TupleStruct(
QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
if args.len() == 1;
if let PatKind::Binding(_, arg, ..) = strip_pat_refs(args[0]).kind;
if let PatKind::Binding(_, arg, ..) = strip_pat_refs(&args[0]).kind;
let body = remove_blocks(arms[0].body);
if path_to_local_id(body, arg);

2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/option_if_let_else.rs
Original file line number Diff line number Diff line change
@@ -132,7 +132,7 @@ fn detect_option_if_let_else<'tcx>(
if !is_else_clause(cx.tcx, expr);
if arms.len() == 2;
if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
if let PatKind::TupleStruct(struct_qpath, [inner_pat], _) = &arms[0].pat.kind;
if is_lang_ctor(cx, struct_qpath, OptionSome);
if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
if !contains_return_break_continue_macro(arms[0].body);
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
Original file line number Diff line number Diff line change
@@ -258,7 +258,7 @@ fn get_variant<'a>(adt_def: &'a AdtDef, qpath: &QPath<'_>) -> Option<&'a Variant

fn find_first_mismatch_in_tuple<'tcx, I>(
cx: &LateContext<'tcx>,
pats: &[&Pat<'_>],
pats: &[Pat<'_>],
ty_iter_src: I,
) -> Option<(Span, Mutability, Level)>
where
18 changes: 9 additions & 9 deletions src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -255,7 +255,7 @@ pub fn in_macro(span: Span) -> bool {
}

/// Checks if given pattern is a wildcard (`_`)
pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
pub fn is_wild(pat: &Pat<'_>) -> bool {
matches!(pat.kind, PatKind::Wild)
}

@@ -1023,8 +1023,8 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
)
}

fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, mut i: I) -> bool {
i.any(|pat| is_refutable(cx, pat))
fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
i.into_iter().any(|pat| is_refutable(cx, pat))
}

match pat.kind {
@@ -1035,23 +1035,23 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
PatKind::Or(pats) => {
// TODO: should be the honest check, that pats is exhaustive set
are_refutable(cx, pats.iter().map(|pat| &**pat))
are_refutable(cx, pats)
},
PatKind::Tuple(pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
PatKind::Tuple(pats, _) => are_refutable(cx, pats),
PatKind::Struct(ref qpath, fields, _) => {
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
},
PatKind::TupleStruct(ref qpath, pats, _) => {
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat))
is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats)
},
PatKind::Slice(head, ref middle, tail) => {
PatKind::Slice(head, middle, tail) => {
match &cx.typeck_results().node_type(pat.hir_id).kind() {
rustc_ty::Slice(..) => {
// [..] is the only irrefutable slice pattern.
!head.is_empty() || middle.is_none() || !tail.is_empty()
},
rustc_ty::Array(..) => {
are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat))
are_refutable(cx, head.iter().chain(middle).chain(tail.iter()))
},
_ => {
// unreachable!()
@@ -1066,7 +1066,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
/// the function once on the given pattern.
pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
if let PatKind::Or(pats) = pat.kind {
pats.iter().copied().for_each(f);
pats.iter().for_each(f);
} else {
f(pat);
}