summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/thir
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /compiler/rustc_middle/src/thir
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/thir')
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs244
1 files changed, 244 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
new file mode 100644
index 000000000..97249fdd1
--- /dev/null
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -0,0 +1,244 @@
+use super::{
+ Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
+};
+
+pub trait Visitor<'a, 'tcx: 'a>: Sized {
+ fn thir(&self) -> &'a Thir<'tcx>;
+
+ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+ walk_expr(self, expr);
+ }
+
+ fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
+ walk_stmt(self, stmt);
+ }
+
+ fn visit_block(&mut self, block: &Block) {
+ walk_block(self, block);
+ }
+
+ fn visit_arm(&mut self, arm: &Arm<'tcx>) {
+ walk_arm(self, arm);
+ }
+
+ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+ walk_pat(self, pat);
+ }
+
+ // Note: We don't have visitors for `ty::Const` and `mir::ConstantKind`
+ // (even though these types occur in THIR) for consistency and to reduce confusion,
+ // since the lazy creation of constants during thir construction causes most
+ // 'constants' to not be of type `ty::Const` or `mir::ConstantKind` at that
+ // stage (they are mostly still identified by `DefId` or `hir::Lit`, see
+ // the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`).
+ // You have to manually visit `ty::Const` and `mir::ConstantKind` through the
+ // other `visit*` functions.
+}
+
+pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
+ use ExprKind::*;
+ match expr.kind {
+ Scope { value, region_scope: _, lint_level: _ } => {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ Box { value } => visitor.visit_expr(&visitor.thir()[value]),
+ If { cond, then, else_opt, if_then_scope: _ } => {
+ visitor.visit_expr(&visitor.thir()[cond]);
+ visitor.visit_expr(&visitor.thir()[then]);
+ if let Some(else_expr) = else_opt {
+ visitor.visit_expr(&visitor.thir()[else_expr]);
+ }
+ }
+ Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
+ visitor.visit_expr(&visitor.thir()[fun]);
+ for &arg in &**args {
+ visitor.visit_expr(&visitor.thir()[arg]);
+ }
+ }
+ Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
+ Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[rhs]);
+ }
+ Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
+ Use { source } => visitor.visit_expr(&visitor.thir()[source]),
+ NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
+ Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
+ Let { expr, .. } => {
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+ Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
+ Match { scrutinee, ref arms } => {
+ visitor.visit_expr(&visitor.thir()[scrutinee]);
+ for &arm in &**arms {
+ visitor.visit_arm(&visitor.thir()[arm]);
+ }
+ }
+ Block { ref body } => visitor.visit_block(body),
+ Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[rhs]);
+ }
+ Field { lhs, variant_index: _, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
+ Index { lhs, index } => {
+ visitor.visit_expr(&visitor.thir()[lhs]);
+ visitor.visit_expr(&visitor.thir()[index]);
+ }
+ VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
+ Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+ Break { value, label: _ } => {
+ if let Some(value) = value {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ }
+ Continue { label: _ } => {}
+ Return { value } => {
+ if let Some(value) = value {
+ visitor.visit_expr(&visitor.thir()[value])
+ }
+ }
+ ConstBlock { did: _, substs: _ } => {}
+ Repeat { value, count: _ } => {
+ visitor.visit_expr(&visitor.thir()[value]);
+ }
+ Array { ref fields } | Tuple { ref fields } => {
+ for &field in &**fields {
+ visitor.visit_expr(&visitor.thir()[field]);
+ }
+ }
+ Adt(box crate::thir::Adt {
+ ref fields,
+ ref base,
+ adt_def: _,
+ variant_index: _,
+ substs: _,
+ user_ty: _,
+ }) => {
+ for field in &**fields {
+ visitor.visit_expr(&visitor.thir()[field.expr]);
+ }
+ if let Some(base) = base {
+ visitor.visit_expr(&visitor.thir()[base.base]);
+ }
+ }
+ PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
+ visitor.visit_expr(&visitor.thir()[source])
+ }
+ Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
+ Literal { lit: _, neg: _ } => {}
+ NonHirLiteral { lit: _, user_ty: _ } => {}
+ ZstLiteral { user_ty: _ } => {}
+ NamedConst { def_id: _, substs: _, user_ty: _ } => {}
+ ConstParam { param: _, def_id: _ } => {}
+ StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
+ InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
+ for op in &**operands {
+ use InlineAsmOperand::*;
+ match op {
+ In { expr, reg: _ }
+ | Out { expr: Some(expr), reg: _, late: _ }
+ | InOut { expr, reg: _, late: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
+ SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
+ visitor.visit_expr(&visitor.thir()[*in_expr]);
+ if let Some(out_expr) = out_expr {
+ visitor.visit_expr(&visitor.thir()[*out_expr]);
+ }
+ }
+ Out { expr: None, reg: _, late: _ }
+ | Const { value: _, span: _ }
+ | SymFn { value: _, span: _ }
+ | SymStatic { def_id: _ } => {}
+ }
+ }
+ }
+ ThreadLocalRef(_) => {}
+ Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
+ }
+}
+
+pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
+ match &stmt.kind {
+ StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
+ StmtKind::Let {
+ initializer,
+ remainder_scope: _,
+ init_scope: _,
+ ref pattern,
+ lint_level: _,
+ else_block,
+ } => {
+ if let Some(init) = initializer {
+ visitor.visit_expr(&visitor.thir()[*init]);
+ }
+ visitor.visit_pat(pattern);
+ if let Some(block) = else_block {
+ visitor.visit_block(block)
+ }
+ }
+ }
+}
+
+pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
+ for &stmt in &*block.stmts {
+ visitor.visit_stmt(&visitor.thir()[stmt]);
+ }
+ if let Some(expr) = block.expr {
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+}
+
+pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
+ match arm.guard {
+ Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
+ Some(Guard::IfLet(ref pat, expr)) => {
+ visitor.visit_pat(pat);
+ visitor.visit_expr(&visitor.thir()[expr]);
+ }
+ None => {}
+ }
+ visitor.visit_pat(&arm.pattern);
+ visitor.visit_expr(&visitor.thir()[arm.body]);
+}
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+ use PatKind::*;
+ match pat.kind.as_ref() {
+ AscribeUserType { subpattern, ascription: _ }
+ | Deref { subpattern }
+ | Binding {
+ subpattern: Some(subpattern),
+ mutability: _,
+ mode: _,
+ var: _,
+ ty: _,
+ is_primary: _,
+ name: _,
+ } => visitor.visit_pat(&subpattern),
+ Binding { .. } | Wild => {}
+ Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+ for subpattern in subpatterns {
+ visitor.visit_pat(&subpattern.pattern);
+ }
+ }
+ Constant { value: _ } => {}
+ Range(_) => {}
+ Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+ for subpattern in prefix {
+ visitor.visit_pat(&subpattern);
+ }
+ if let Some(pat) = slice {
+ visitor.visit_pat(pat);
+ }
+ for subpattern in suffix {
+ visitor.visit_pat(&subpattern);
+ }
+ }
+ Or { pats } => {
+ for pat in pats {
+ visitor.visit_pat(&pat);
+ }
+ }
+ };
+}