1 use crate::def
::{CtorOf, DefKind, Res}
;
2 use crate::def_id
::DefId
;
3 use crate::hir
::{self, HirId, PatKind}
;
4 use rustc_data_structures
::stable_set
::FxHashSet
;
5 use rustc_span
::symbol
::Ident
;
8 use std
::iter
::{Enumerate, ExactSizeIterator}
;
10 pub struct EnumerateAndAdjust
<I
> {
11 enumerate
: Enumerate
<I
>,
16 impl<I
> Iterator
for EnumerateAndAdjust
<I
>
20 type Item
= (usize, <I
as Iterator
>::Item
);
22 fn next(&mut self) -> Option
<(usize, <I
as Iterator
>::Item
)> {
25 .map(|(i
, elem
)| (if i
< self.gap_pos { i }
else { i + self.gap_len }
, elem
))
28 fn size_hint(&self) -> (usize, Option
<usize>) {
29 self.enumerate
.size_hint()
33 pub trait EnumerateAndAdjustIterator
{
34 fn enumerate_and_adjust(
37 gap_pos
: Option
<usize>,
38 ) -> EnumerateAndAdjust
<Self>
43 impl<T
: ExactSizeIterator
> EnumerateAndAdjustIterator
for T
{
44 fn enumerate_and_adjust(
47 gap_pos
: Option
<usize>,
48 ) -> EnumerateAndAdjust
<Self>
52 let actual_len
= self.len();
54 enumerate
: self.enumerate(),
55 gap_pos
: gap_pos
.unwrap_or(expected_len
),
56 gap_len
: expected_len
- actual_len
,
62 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
63 /// `match foo() { Some(a) => (), None => () }`
64 pub fn each_binding(&self, mut f
: impl FnMut(hir
::BindingAnnotation
, HirId
, Span
, Ident
)) {
65 self.walk_always(|p
| {
66 if let PatKind
::Binding(binding_mode
, _
, ident
, _
) = p
.kind
{
67 f(binding_mode
, p
.hir_id
, p
.span
, ident
);
72 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
73 /// `match foo() { Some(a) => (), None => () }`.
75 /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
76 pub fn each_binding_or_first(
78 f
: &mut impl FnMut(hir
::BindingAnnotation
, HirId
, Span
, Ident
),
80 self.walk(|p
| match &p
.kind
{
82 ps
[0].each_binding_or_first(f
);
85 PatKind
::Binding(bm
, _
, ident
, _
) => {
86 f(*bm
, p
.hir_id
, p
.span
, *ident
);
93 pub fn simple_ident(&self) -> Option
<Ident
> {
96 hir
::BindingAnnotation
::Unannotated
| hir
::BindingAnnotation
::Mutable
,
105 /// Returns variants that are necessary to exist for the pattern to match.
106 pub fn necessary_variants(&self) -> Vec
<DefId
> {
107 let mut variants
= vec
![];
108 self.walk(|p
| match &p
.kind
{
109 PatKind
::Or(_
) => false,
110 PatKind
::Path(hir
::QPath
::Resolved(_
, path
))
111 | PatKind
::TupleStruct(hir
::QPath
::Resolved(_
, path
), ..)
112 | PatKind
::Struct(hir
::QPath
::Resolved(_
, path
), ..) => {
113 if let Res
::Def(DefKind
::Variant
| DefKind
::Ctor(CtorOf
::Variant
, ..), id
) =
122 // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
124 let mut duplicates
= FxHashSet
::default();
125 variants
.retain(|def_id
| duplicates
.insert(*def_id
));
129 /// Checks if the pattern contains any `ref` or `ref mut` bindings, and if
130 /// yes whether it contains mutable or just immutables ones.
132 // FIXME(tschottdorf): this is problematic as the HIR is being scraped, but
133 // ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
134 pub fn contains_explicit_ref_binding(&self) -> Option
<hir
::Mutability
> {
135 let mut result
= None
;
136 self.each_binding(|annotation
, _
, _
, _
| match annotation
{
137 hir
::BindingAnnotation
::Ref
=> match result
{
138 None
| Some(hir
::Mutability
::Not
) => result
= Some(hir
::Mutability
::Not
),
141 hir
::BindingAnnotation
::RefMut
=> result
= Some(hir
::Mutability
::Mut
),