@@ -818,3 +818,246 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
818818 }
819819 }
820820}
821+
822+ pub mod visit {
823+ use super :: * ;
824+ pub trait Visitor < ' a , ' tcx : ' a > : Sized {
825+ fn thir ( & self ) -> & ' a Thir < ' tcx > ;
826+
827+ fn visit_expr ( & mut self , expr : & Expr < ' tcx > ) {
828+ walk_expr ( self , expr) ;
829+ }
830+
831+ fn visit_stmt ( & mut self , stmt : & Stmt < ' tcx > ) {
832+ walk_stmt ( self , stmt) ;
833+ }
834+
835+ fn visit_block ( & mut self , block : & Block ) {
836+ walk_block ( self , block) ;
837+ }
838+
839+ fn visit_arm ( & mut self , arm : & Arm < ' tcx > ) {
840+ walk_arm ( self , arm) ;
841+ }
842+
843+ fn visit_pat ( & mut self , pat : & Pat < ' tcx > ) {
844+ walk_pat ( self , pat) ;
845+ }
846+
847+ fn visit_const ( & mut self , _cnst : & ' tcx Const < ' tcx > ) { }
848+ }
849+
850+ pub fn walk_expr < ' a , ' tcx : ' a , V : Visitor < ' a , ' tcx > > ( visitor : & mut V , expr : & Expr < ' tcx > ) {
851+ use ExprKind :: * ;
852+ match expr. kind {
853+ Scope { value, region_scope : _, lint_level : _ } => {
854+ visitor. visit_expr ( & visitor. thir ( ) [ value] )
855+ }
856+ Box { value } => visitor. visit_expr ( & visitor. thir ( ) [ value] ) ,
857+ If { cond, then, else_opt, if_then_scope : _ } => {
858+ visitor. visit_expr ( & visitor. thir ( ) [ cond] ) ;
859+ visitor. visit_expr ( & visitor. thir ( ) [ then] ) ;
860+ if let Some ( else_expr) = else_opt {
861+ visitor. visit_expr ( & visitor. thir ( ) [ else_expr] ) ;
862+ }
863+ }
864+ Call { fun, ref args, ty : _, from_hir_call : _, fn_span : _ } => {
865+ visitor. visit_expr ( & visitor. thir ( ) [ fun] ) ;
866+ for & arg in & * * args {
867+ visitor. visit_expr ( & visitor. thir ( ) [ arg] ) ;
868+ }
869+ }
870+ Deref { arg } => visitor. visit_expr ( & visitor. thir ( ) [ arg] ) ,
871+ Binary { lhs, rhs, op : _ } | LogicalOp { lhs, rhs, op : _ } => {
872+ visitor. visit_expr ( & visitor. thir ( ) [ lhs] ) ;
873+ visitor. visit_expr ( & visitor. thir ( ) [ rhs] ) ;
874+ }
875+ Unary { arg, op : _ } => visitor. visit_expr ( & visitor. thir ( ) [ arg] ) ,
876+ Cast { source } => visitor. visit_expr ( & visitor. thir ( ) [ source] ) ,
877+ Use { source } => visitor. visit_expr ( & visitor. thir ( ) [ source] ) ,
878+ NeverToAny { source } => visitor. visit_expr ( & visitor. thir ( ) [ source] ) ,
879+ Pointer { source, cast : _ } => visitor. visit_expr ( & visitor. thir ( ) [ source] ) ,
880+ Let { expr, .. } => {
881+ visitor. visit_expr ( & visitor. thir ( ) [ expr] ) ;
882+ }
883+ Loop { body } => visitor. visit_expr ( & visitor. thir ( ) [ body] ) ,
884+ Match { scrutinee, ref arms } => {
885+ visitor. visit_expr ( & visitor. thir ( ) [ scrutinee] ) ;
886+ for & arm in & * * arms {
887+ visitor. visit_arm ( & visitor. thir ( ) [ arm] ) ;
888+ }
889+ }
890+ Block { ref body } => visitor. visit_block ( body) ,
891+ Assign { lhs, rhs } | AssignOp { lhs, rhs, op : _ } => {
892+ visitor. visit_expr ( & visitor. thir ( ) [ lhs] ) ;
893+ visitor. visit_expr ( & visitor. thir ( ) [ rhs] ) ;
894+ }
895+ Field { lhs, name : _ } => visitor. visit_expr ( & visitor. thir ( ) [ lhs] ) ,
896+ Index { lhs, index } => {
897+ visitor. visit_expr ( & visitor. thir ( ) [ lhs] ) ;
898+ visitor. visit_expr ( & visitor. thir ( ) [ index] ) ;
899+ }
900+ VarRef { id : _ } | UpvarRef { closure_def_id : _, var_hir_id : _ } => { }
901+ Borrow { arg, borrow_kind : _ } => visitor. visit_expr ( & visitor. thir ( ) [ arg] ) ,
902+ AddressOf { arg, mutability : _ } => visitor. visit_expr ( & visitor. thir ( ) [ arg] ) ,
903+ Break { value, label : _ } => {
904+ if let Some ( value) = value {
905+ visitor. visit_expr ( & visitor. thir ( ) [ value] )
906+ }
907+ }
908+ Continue { label : _ } => { }
909+ Return { value } => {
910+ if let Some ( value) = value {
911+ visitor. visit_expr ( & visitor. thir ( ) [ value] )
912+ }
913+ }
914+ ConstBlock { value } => visitor. visit_const ( value) ,
915+ Repeat { value, count } => {
916+ visitor. visit_expr ( & visitor. thir ( ) [ value] ) ;
917+ visitor. visit_const ( count) ;
918+ }
919+ Array { ref fields } | Tuple { ref fields } => {
920+ for & field in & * * fields {
921+ visitor. visit_expr ( & visitor. thir ( ) [ field] ) ;
922+ }
923+ }
924+ Adt ( box crate :: thir:: Adt {
925+ ref fields,
926+ ref base,
927+ adt_def : _,
928+ variant_index : _,
929+ substs : _,
930+ user_ty : _,
931+ } ) => {
932+ for field in & * * fields {
933+ visitor. visit_expr ( & visitor. thir ( ) [ field. expr ] ) ;
934+ }
935+ if let Some ( base) = base {
936+ visitor. visit_expr ( & visitor. thir ( ) [ base. base ] ) ;
937+ }
938+ }
939+ PlaceTypeAscription { source, user_ty : _ }
940+ | ValueTypeAscription { source, user_ty : _ } => {
941+ visitor. visit_expr ( & visitor. thir ( ) [ source] )
942+ }
943+ Closure { closure_id : _, substs : _, upvars : _, movability : _, fake_reads : _ } => { }
944+ Literal { literal, user_ty : _, const_id : _ } => visitor. visit_const ( literal) ,
945+ StaticRef { literal, def_id : _ } => visitor. visit_const ( literal) ,
946+ InlineAsm { ref operands, template : _, options : _, line_spans : _ } => {
947+ for op in & * * operands {
948+ use InlineAsmOperand :: * ;
949+ match op {
950+ In { expr, reg : _ }
951+ | Out { expr : Some ( expr) , reg : _, late : _ }
952+ | InOut { expr, reg : _, late : _ }
953+ | SymFn { expr } => visitor. visit_expr ( & visitor. thir ( ) [ * expr] ) ,
954+ SplitInOut { in_expr, out_expr, reg : _, late : _ } => {
955+ visitor. visit_expr ( & visitor. thir ( ) [ * in_expr] ) ;
956+ if let Some ( out_expr) = out_expr {
957+ visitor. visit_expr ( & visitor. thir ( ) [ * out_expr] ) ;
958+ }
959+ }
960+ Out { expr : None , reg : _, late : _ }
961+ | Const { value : _, span : _ }
962+ | SymStatic { def_id : _ } => { }
963+ }
964+ }
965+ }
966+ ThreadLocalRef ( _) => { }
967+ LlvmInlineAsm { ref outputs, ref inputs, asm : _ } => {
968+ for & out_expr in & * * outputs {
969+ visitor. visit_expr ( & visitor. thir ( ) [ out_expr] ) ;
970+ }
971+ for & in_expr in & * * inputs {
972+ visitor. visit_expr ( & visitor. thir ( ) [ in_expr] ) ;
973+ }
974+ }
975+ Yield { value } => visitor. visit_expr ( & visitor. thir ( ) [ value] ) ,
976+ }
977+ }
978+
979+ pub fn walk_stmt < ' a , ' tcx : ' a , V : Visitor < ' a , ' tcx > > ( visitor : & mut V , stmt : & Stmt < ' tcx > ) {
980+ match & stmt. kind {
981+ StmtKind :: Expr { expr, scope : _ } => visitor. visit_expr ( & visitor. thir ( ) [ * expr] ) ,
982+ StmtKind :: Let {
983+ initializer,
984+ remainder_scope : _,
985+ init_scope : _,
986+ ref pattern,
987+ lint_level : _,
988+ } => {
989+ if let Some ( init) = initializer {
990+ visitor. visit_expr ( & visitor. thir ( ) [ * init] ) ;
991+ }
992+ visitor. visit_pat ( pattern) ;
993+ }
994+ }
995+ }
996+
997+ pub fn walk_block < ' a , ' tcx : ' a , V : Visitor < ' a , ' tcx > > ( visitor : & mut V , block : & Block ) {
998+ for & stmt in & * block. stmts {
999+ visitor. visit_stmt ( & visitor. thir ( ) [ stmt] ) ;
1000+ }
1001+ if let Some ( expr) = block. expr {
1002+ visitor. visit_expr ( & visitor. thir ( ) [ expr] ) ;
1003+ }
1004+ }
1005+
1006+ pub fn walk_arm < ' a , ' tcx : ' a , V : Visitor < ' a , ' tcx > > ( visitor : & mut V , arm : & Arm < ' tcx > ) {
1007+ match arm. guard {
1008+ Some ( Guard :: If ( expr) ) => visitor. visit_expr ( & visitor. thir ( ) [ expr] ) ,
1009+ Some ( Guard :: IfLet ( ref pat, expr) ) => {
1010+ visitor. visit_pat ( pat) ;
1011+ visitor. visit_expr ( & visitor. thir ( ) [ expr] ) ;
1012+ }
1013+ None => { }
1014+ }
1015+ visitor. visit_pat ( & arm. pattern ) ;
1016+ visitor. visit_expr ( & visitor. thir ( ) [ arm. body ] ) ;
1017+ }
1018+
1019+ pub fn walk_pat < ' a , ' tcx : ' a , V : Visitor < ' a , ' tcx > > ( visitor : & mut V , pat : & Pat < ' tcx > ) {
1020+ use PatKind :: * ;
1021+ match pat. kind . as_ref ( ) {
1022+ AscribeUserType { subpattern, ascription : _ }
1023+ | Deref { subpattern }
1024+ | Binding {
1025+ subpattern : Some ( subpattern) ,
1026+ mutability : _,
1027+ mode : _,
1028+ var : _,
1029+ ty : _,
1030+ is_primary : _,
1031+ name : _,
1032+ } => visitor. visit_pat ( & subpattern) ,
1033+ Binding { .. } | Wild => { }
1034+ Variant { subpatterns, adt_def : _, substs : _, variant_index : _ }
1035+ | Leaf { subpatterns } => {
1036+ for subpattern in subpatterns {
1037+ visitor. visit_pat ( & subpattern. pattern ) ;
1038+ }
1039+ }
1040+ Constant { value } => visitor. visit_const ( value) ,
1041+ Range ( range) => {
1042+ visitor. visit_const ( range. lo ) ;
1043+ visitor. visit_const ( range. hi ) ;
1044+ }
1045+ Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
1046+ for subpattern in prefix {
1047+ visitor. visit_pat ( & subpattern) ;
1048+ }
1049+ if let Some ( pat) = slice {
1050+ visitor. visit_pat ( pat) ;
1051+ }
1052+ for subpattern in suffix {
1053+ visitor. visit_pat ( & subpattern) ;
1054+ }
1055+ }
1056+ Or { pats } => {
1057+ for pat in pats {
1058+ visitor. visit_pat ( & pat) ;
1059+ }
1060+ }
1061+ } ;
1062+ }
1063+ }
0 commit comments