summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/thir.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/thir.rs')
-rw-r--r--compiler/rustc_middle/src/thir.rs68
1 files changed, 60 insertions, 8 deletions
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 3b11fab8c..7d79a13d3 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -17,14 +17,14 @@ use rustc_index::newtype_index;
use rustc_index::vec::IndexVec;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
-use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
+use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::asm::InlineAsmRegOrRegClass;
use std::fmt;
use std::ops::Index;
@@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> {
/// The lint level for this `let` statement.
lint_level: LintLevel,
+
+ /// Span of the `let <PAT> = <INIT>` part.
+ span: Span,
},
}
@@ -366,7 +369,7 @@ pub enum ExprKind<'tcx> {
/// Variant containing the field.
variant_index: VariantIdx,
/// This can be a named (`.foo`) or unnamed (`.0`) field.
- name: Field,
+ name: FieldIdx,
},
/// A *non-overloaded* indexing operation.
Index {
@@ -491,7 +494,7 @@ pub enum ExprKind<'tcx> {
/// This is used in struct constructors.
#[derive(Clone, Debug, HashStable)]
pub struct FieldExpr {
- pub name: Field,
+ pub name: FieldIdx,
pub expr: ExprId,
}
@@ -570,7 +573,7 @@ pub enum BindingMode {
#[derive(Clone, Debug, HashStable)]
pub struct FieldPat<'tcx> {
- pub field: Field,
+ pub field: FieldIdx,
pub pattern: Box<Pat<'tcx>>,
}
@@ -594,6 +597,55 @@ impl<'tcx> Pat<'tcx> {
_ => None,
}
}
+
+ /// 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(Symbol, BindingMode, Ty<'tcx>, Span)) {
+ self.walk_always(|p| {
+ if let PatKind::Binding { name, mode, ty, .. } = p.kind {
+ f(name, mode, ty, p.span);
+ }
+ });
+ }
+
+ /// Walk the pattern in left-to-right order.
+ ///
+ /// If `it(pat)` returns `false`, the children are not visited.
+ pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
+ self.walk_(&mut it)
+ }
+
+ fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
+ if !it(self) {
+ return;
+ }
+
+ use PatKind::*;
+ match &self.kind {
+ Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
+ AscribeUserType { subpattern, .. }
+ | Binding { subpattern: Some(subpattern), .. }
+ | Deref { subpattern } => subpattern.walk_(it),
+ Leaf { subpatterns } | Variant { subpatterns, .. } => {
+ subpatterns.iter().for_each(|field| field.pattern.walk_(it))
+ }
+ Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
+ Array { box ref prefix, ref slice, box ref suffix }
+ | Slice { box ref prefix, ref slice, box ref suffix } => {
+ prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
+ }
+ }
+ }
+
+ /// Walk the pattern in left-to-right order.
+ ///
+ /// If you always want to recurse, prefer this method over `walk`.
+ pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
+ self.walk(|p| {
+ it(p);
+ true
+ })
+ }
}
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
@@ -784,7 +836,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
if let PatKind::Wild = p.pattern.kind {
continue;
}
- let name = variant.fields[p.field.index()].name;
+ let name = variant.fields[p.field].name;
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
printed += 1;
}
@@ -879,7 +931,7 @@ mod size_asserts {
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 56);
- static_assert_size!(Stmt<'_>, 48);
- static_assert_size!(StmtKind<'_>, 40);
+ static_assert_size!(Stmt<'_>, 56);
+ static_assert_size!(StmtKind<'_>, 48);
// tidy-alphabetical-end
}