2020-01-02 05:18:45 +01:00
|
|
|
use crate::def::{CtorOf, DefKind, Res};
|
|
|
|
|
use crate::def_id::DefId;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::hir::{self, HirId, PatKind};
|
2021-03-28 00:51:31 -04:00
|
|
|
use rustc_data_structures::stable_set::FxHashSet;
|
2021-10-25 23:33:12 -05:00
|
|
|
use rustc_span::hygiene::DesugaringKind;
|
2020-04-19 13:00:18 +02:00
|
|
|
use rustc_span::symbol::Ident;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::Span;
|
2012-01-14 16:05:07 -08:00
|
|
|
|
2016-03-06 15:54:44 +03:00
|
|
|
use std::iter::{Enumerate, ExactSizeIterator};
|
2015-11-04 00:02:22 -06:00
|
|
|
|
2016-03-06 15:54:44 +03:00
|
|
|
pub struct EnumerateAndAdjust<I> {
|
|
|
|
|
enumerate: Enumerate<I>,
|
2016-03-06 15:54:44 +03:00
|
|
|
gap_pos: usize,
|
|
|
|
|
gap_len: usize,
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
impl<I> Iterator for EnumerateAndAdjust<I>
|
|
|
|
|
where
|
|
|
|
|
I: Iterator,
|
|
|
|
|
{
|
2016-03-06 15:54:44 +03:00
|
|
|
type Item = (usize, <I as Iterator>::Item);
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
|
2019-12-22 17:42:04 -05:00
|
|
|
self.enumerate
|
|
|
|
|
.next()
|
|
|
|
|
.map(|(i, elem)| (if i < self.gap_pos { i } else { i + self.gap_len }, elem))
|
2016-03-06 15:54:44 +03:00
|
|
|
}
|
2018-03-20 05:33:59 -04:00
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
|
self.enumerate.size_hint()
|
|
|
|
|
}
|
2016-03-06 15:54:44 +03:00
|
|
|
}
|
|
|
|
|
|
2016-03-06 15:54:44 +03:00
|
|
|
pub trait EnumerateAndAdjustIterator {
|
2019-12-22 17:42:04 -05:00
|
|
|
fn enumerate_and_adjust(
|
|
|
|
|
self,
|
|
|
|
|
expected_len: usize,
|
|
|
|
|
gap_pos: Option<usize>,
|
|
|
|
|
) -> EnumerateAndAdjust<Self>
|
|
|
|
|
where
|
|
|
|
|
Self: Sized;
|
2016-03-06 15:54:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
2019-12-22 17:42:04 -05:00
|
|
|
fn enumerate_and_adjust(
|
|
|
|
|
self,
|
|
|
|
|
expected_len: usize,
|
|
|
|
|
gap_pos: Option<usize>,
|
|
|
|
|
) -> EnumerateAndAdjust<Self>
|
|
|
|
|
where
|
|
|
|
|
Self: Sized,
|
|
|
|
|
{
|
2016-03-06 15:54:44 +03:00
|
|
|
let actual_len = self.len();
|
|
|
|
|
EnumerateAndAdjust {
|
|
|
|
|
enumerate: self.enumerate(),
|
2018-04-03 08:45:06 +09:00
|
|
|
gap_pos: gap_pos.unwrap_or(expected_len),
|
2016-03-06 15:54:44 +03:00
|
|
|
gap_len: expected_len - actual_len,
|
|
|
|
|
}
|
2016-03-06 15:54:44 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-29 13:43:03 +01:00
|
|
|
impl hir::Pat<'_> {
|
2016-11-25 13:21:19 +02:00
|
|
|
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
|
|
|
|
/// `match foo() { Some(a) => (), None => () }`
|
2020-04-19 13:00:18 +02:00
|
|
|
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, Ident)) {
|
2019-12-14 23:43:21 +01:00
|
|
|
self.walk_always(|p| {
|
2019-09-26 16:18:31 +01:00
|
|
|
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
|
2018-06-10 19:33:30 +03:00
|
|
|
f(binding_mode, p.hir_id, p.span, ident);
|
2016-11-25 13:21:19 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2014-01-15 14:39:08 -05:00
|
|
|
|
2019-09-15 03:41:21 +02:00
|
|
|
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
|
|
|
|
/// `match foo() { Some(a) => (), None => () }`.
|
|
|
|
|
///
|
|
|
|
|
/// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
|
2019-09-21 15:49:15 +02:00
|
|
|
pub fn each_binding_or_first(
|
|
|
|
|
&self,
|
2020-04-19 13:00:18 +02:00
|
|
|
f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
|
2019-09-21 15:49:15 +02:00
|
|
|
) {
|
2019-09-26 16:18:31 +01:00
|
|
|
self.walk(|p| match &p.kind {
|
2019-09-21 15:49:15 +02:00
|
|
|
PatKind::Or(ps) => {
|
|
|
|
|
ps[0].each_binding_or_first(f);
|
|
|
|
|
false
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
|
|
|
|
PatKind::Binding(bm, _, ident, _) => {
|
2019-09-21 15:49:15 +02:00
|
|
|
f(*bm, p.hir_id, p.span, *ident);
|
|
|
|
|
true
|
2019-09-15 03:41:21 +02:00
|
|
|
}
|
2019-09-21 15:49:15 +02:00
|
|
|
_ => true,
|
|
|
|
|
})
|
2019-09-15 03:41:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-19 13:00:18 +02:00
|
|
|
pub fn simple_ident(&self) -> Option<Ident> {
|
2019-09-26 16:18:31 +01:00
|
|
|
match self.kind {
|
2020-04-16 17:38:52 -07:00
|
|
|
PatKind::Binding(
|
|
|
|
|
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
|
|
|
|
|
_,
|
|
|
|
|
ident,
|
|
|
|
|
None,
|
|
|
|
|
) => Some(ident),
|
2018-05-11 22:24:04 +08:00
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Returns variants that are necessary to exist for the pattern to match.
|
2016-11-25 13:21:19 +02:00
|
|
|
pub fn necessary_variants(&self) -> Vec<DefId> {
|
|
|
|
|
let mut variants = vec![];
|
2019-09-26 16:18:31 +01:00
|
|
|
self.walk(|p| match &p.kind {
|
2019-09-21 15:49:15 +02:00
|
|
|
PatKind::Or(_) => false,
|
2019-12-22 17:42:04 -05:00
|
|
|
PatKind::Path(hir::QPath::Resolved(_, path))
|
|
|
|
|
| PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..)
|
|
|
|
|
| PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
|
2020-04-16 17:38:52 -07:00
|
|
|
if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) =
|
|
|
|
|
path.res
|
2019-09-21 15:49:15 +02:00
|
|
|
{
|
|
|
|
|
variants.push(id);
|
2016-11-25 13:21:19 +02:00
|
|
|
}
|
2019-09-21 15:49:15 +02:00
|
|
|
true
|
2016-11-25 13:21:19 +02:00
|
|
|
}
|
2019-09-21 15:49:15 +02:00
|
|
|
_ => true,
|
2016-11-25 13:21:19 +02:00
|
|
|
});
|
2021-03-28 00:51:31 -04:00
|
|
|
// We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
|
|
|
|
|
// the bounds
|
|
|
|
|
let mut duplicates = FxHashSet::default();
|
|
|
|
|
variants.retain(|def_id| duplicates.insert(*def_id));
|
2016-11-25 13:21:19 +02:00
|
|
|
variants
|
|
|
|
|
}
|
2015-06-02 20:31:40 +09:00
|
|
|
|
2017-10-06 16:30:23 -04:00
|
|
|
/// Checks if the pattern contains any `ref` or `ref mut` bindings, and if
|
|
|
|
|
/// yes whether it contains mutable or just immutables ones.
|
2019-02-08 14:53:55 +01:00
|
|
|
//
|
|
|
|
|
// FIXME(tschottdorf): this is problematic as the HIR is being scraped, but
|
|
|
|
|
// ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
|
2017-07-21 19:29:43 -04:00
|
|
|
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
|
2016-11-25 13:21:19 +02:00
|
|
|
let mut result = None;
|
2019-12-22 17:42:04 -05:00
|
|
|
self.each_binding(|annotation, _, _, _| match annotation {
|
|
|
|
|
hir::BindingAnnotation::Ref => match result {
|
|
|
|
|
None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
|
2019-09-21 15:49:15 +02:00
|
|
|
_ => {}
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
|
hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
|
|
|
|
|
_ => {}
|
2016-11-25 13:21:19 +02:00
|
|
|
});
|
|
|
|
|
result
|
|
|
|
|
}
|
2021-10-25 23:33:12 -05:00
|
|
|
|
|
|
|
|
/// If the pattern is `Some(<pat>)` from a desugared for loop, returns the inner pattern
|
|
|
|
|
pub fn for_loop_some(&self) -> Option<&Self> {
|
|
|
|
|
if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
|
|
|
|
|
if let hir::PatKind::Struct(_, [pat_field], _) = self.kind {
|
|
|
|
|
return Some(pat_field.pat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
2016-11-25 13:21:19 +02:00
|
|
|
}
|