mv compiler to compiler/
This commit is contained in:
parent
db534b3ac2
commit
9e5f7d5631
1686 changed files with 941 additions and 1051 deletions
194
compiler/rustc_hir/src/pat_util.rs
Normal file
194
compiler/rustc_hir/src/pat_util.rs
Normal file
|
@ -0,0 +1,194 @@
|
|||
use crate::def::{CtorOf, DefKind, Res};
|
||||
use crate::def_id::DefId;
|
||||
use crate::hir::{self, HirId, PatKind};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter::{Enumerate, ExactSizeIterator};
|
||||
|
||||
pub struct EnumerateAndAdjust<I> {
|
||||
enumerate: Enumerate<I>,
|
||||
gap_pos: usize,
|
||||
gap_len: usize,
|
||||
}
|
||||
|
||||
impl<I> Iterator for EnumerateAndAdjust<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = (usize, <I as Iterator>::Item);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
|
||||
self.enumerate
|
||||
.next()
|
||||
.map(|(i, elem)| (if i < self.gap_pos { i } else { i + self.gap_len }, elem))
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.enumerate.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EnumerateAndAdjustIterator {
|
||||
fn enumerate_and_adjust(
|
||||
self,
|
||||
expected_len: usize,
|
||||
gap_pos: Option<usize>,
|
||||
) -> EnumerateAndAdjust<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
||||
fn enumerate_and_adjust(
|
||||
self,
|
||||
expected_len: usize,
|
||||
gap_pos: Option<usize>,
|
||||
) -> EnumerateAndAdjust<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let actual_len = self.len();
|
||||
EnumerateAndAdjust {
|
||||
enumerate: self.enumerate(),
|
||||
gap_pos: gap_pos.unwrap_or(expected_len),
|
||||
gap_len: expected_len - actual_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl hir::Pat<'_> {
|
||||
pub fn is_refutable(&self) -> bool {
|
||||
match self.kind {
|
||||
PatKind::Lit(_)
|
||||
| PatKind::Range(..)
|
||||
| PatKind::Path(hir::QPath::Resolved(Some(..), _) | hir::QPath::TypeRelative(..)) => {
|
||||
true
|
||||
}
|
||||
|
||||
PatKind::Path(hir::QPath::Resolved(_, ref path))
|
||||
| PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..)
|
||||
| PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => match path.res {
|
||||
Res::Def(DefKind::Variant, _) => true,
|
||||
_ => false,
|
||||
},
|
||||
PatKind::Slice(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
||||
/// `match foo() { Some(a) => (), None => () }`
|
||||
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, Ident)) {
|
||||
self.walk_always(|p| {
|
||||
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
|
||||
f(binding_mode, p.hir_id, p.span, ident);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn each_binding_or_first(
|
||||
&self,
|
||||
f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
|
||||
) {
|
||||
self.walk(|p| match &p.kind {
|
||||
PatKind::Or(ps) => {
|
||||
ps[0].each_binding_or_first(f);
|
||||
false
|
||||
}
|
||||
PatKind::Binding(bm, _, ident, _) => {
|
||||
f(*bm, p.hir_id, p.span, *ident);
|
||||
true
|
||||
}
|
||||
_ => true,
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the pattern contains any patterns that bind something to
|
||||
/// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
|
||||
pub fn contains_bindings(&self) -> bool {
|
||||
self.satisfies(|p| match p.kind {
|
||||
PatKind::Binding(..) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the pattern contains any patterns that bind something to
|
||||
/// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`,
|
||||
pub fn contains_bindings_or_wild(&self) -> bool {
|
||||
self.satisfies(|p| match p.kind {
|
||||
PatKind::Binding(..) | PatKind::Wild => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the pattern satisfies the given predicate on some sub-pattern.
|
||||
fn satisfies(&self, pred: impl Fn(&hir::Pat<'_>) -> bool) -> bool {
|
||||
let mut satisfies = false;
|
||||
self.walk_short(|p| {
|
||||
if pred(p) {
|
||||
satisfies = true;
|
||||
false // Found one, can short circuit now.
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
satisfies
|
||||
}
|
||||
|
||||
pub fn simple_ident(&self) -> Option<Ident> {
|
||||
match self.kind {
|
||||
PatKind::Binding(
|
||||
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
|
||||
_,
|
||||
ident,
|
||||
None,
|
||||
) => Some(ident),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns variants that are necessary to exist for the pattern to match.
|
||||
pub fn necessary_variants(&self) -> Vec<DefId> {
|
||||
let mut variants = vec![];
|
||||
self.walk(|p| match &p.kind {
|
||||
PatKind::Or(_) => false,
|
||||
PatKind::Path(hir::QPath::Resolved(_, path))
|
||||
| PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..)
|
||||
| PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
|
||||
if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) =
|
||||
path.res
|
||||
{
|
||||
variants.push(id);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => true,
|
||||
});
|
||||
variants.sort();
|
||||
variants.dedup();
|
||||
variants
|
||||
}
|
||||
|
||||
/// Checks if the pattern contains any `ref` or `ref mut` bindings, and if
|
||||
/// yes whether it contains mutable or just immutables ones.
|
||||
//
|
||||
// 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.
|
||||
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
|
||||
let mut result = None;
|
||||
self.each_binding(|annotation, _, _, _| match annotation {
|
||||
hir::BindingAnnotation::Ref => match result {
|
||||
None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
|
||||
_ => {}
|
||||
},
|
||||
hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
|
||||
_ => {}
|
||||
});
|
||||
result
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue