@@ -818,3 +818,246 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
818
818
}
819
819
}
820
820
}
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