@@ -20,8 +20,10 @@ use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call};
20
20
use syntax:: ast:: { expr_unary, unsafe_fn, expr_path} ;
21
21
use syntax:: ast;
22
22
use syntax:: codemap:: span;
23
- use syntax:: oldvisit:: { fk_item_fn, fk_method} ;
24
- use syntax:: oldvisit;
23
+ use syntax:: visit:: { fk_item_fn, fk_method} ;
24
+ use syntax:: visit;
25
+ use syntax:: visit:: { Visitor , fn_kind} ;
26
+ use syntax:: ast:: { fn_decl, Block , NodeId , expr} ;
25
27
26
28
#[ deriving( Eq ) ]
27
29
enum UnsafeContext {
@@ -45,120 +47,133 @@ fn type_is_unsafe_function(ty: ty::t) -> bool {
45
47
}
46
48
}
47
49
48
- pub fn check_crate ( tcx : ty:: ctxt ,
49
- method_map : method_map ,
50
- crate : & ast:: Crate ) {
51
- let context = @mut Context {
52
- method_map : method_map,
53
- unsafe_context : SafeContext ,
54
- } ;
50
+ struct EffectCheckVisitor {
51
+ tcx : ty:: ctxt ,
52
+ context : @mut Context ,
53
+ }
55
54
56
- let require_unsafe : @ fn ( span : span ,
57
- description : & str ) = |span , description| {
58
- match context. unsafe_context {
55
+ impl EffectCheckVisitor {
56
+ fn require_unsafe ( & mut self , span : span , description : & str ) {
57
+ match self . context . unsafe_context {
59
58
SafeContext => {
60
59
// Report an error.
61
- tcx. sess . span_err ( span,
60
+ self . tcx . sess . span_err ( span,
62
61
fmt ! ( "%s requires unsafe function or block" ,
63
62
description) )
64
63
}
65
64
UnsafeBlock ( block_id) => {
66
65
// OK, but record this.
67
66
debug ! ( "effect: recording unsafe block as used: %?" , block_id) ;
68
- let _ = tcx. used_unsafe . insert ( block_id) ;
67
+ let _ = self . tcx . used_unsafe . insert ( block_id) ;
69
68
}
70
69
UnsafeFn => { }
71
70
}
72
- } ;
71
+ }
72
+ }
73
+
74
+ impl Visitor < ( ) > for EffectCheckVisitor {
75
+ fn visit_fn ( & mut self , fn_kind : & fn_kind , fn_decl : & fn_decl ,
76
+ block : & Block , span : span , node_id : NodeId , _: ( ) ) {
73
77
74
- let visitor = oldvisit:: mk_vt ( @oldvisit:: Visitor {
75
- visit_fn : |fn_kind, fn_decl, block, span, node_id, ( _, visitor) | {
76
78
let ( is_item_fn, is_unsafe_fn) = match * fn_kind {
77
79
fk_item_fn( _, _, purity, _) => ( true , purity == unsafe_fn) ,
78
80
fk_method( _, _, method) => ( true , method. purity == unsafe_fn) ,
79
81
_ => ( false , false ) ,
80
82
} ;
81
83
82
- let old_unsafe_context = context. unsafe_context ;
84
+ let old_unsafe_context = self . context . unsafe_context ;
83
85
if is_unsafe_fn {
84
- context. unsafe_context = UnsafeFn
86
+ self . context . unsafe_context = UnsafeFn
85
87
} else if is_item_fn {
86
- context. unsafe_context = SafeContext
88
+ self . context . unsafe_context = SafeContext
87
89
}
88
90
89
- oldvisit:: visit_fn ( fn_kind,
91
+ visit:: walk_fn ( self ,
92
+ fn_kind,
90
93
fn_decl,
91
94
block,
92
95
span,
93
96
node_id,
94
- ( ( ) ,
95
- visitor) ) ;
97
+ ( ) ) ;
98
+
99
+ self . context . unsafe_context = old_unsafe_context
100
+ }
96
101
97
- context. unsafe_context = old_unsafe_context
98
- } ,
102
+ fn visit_block ( & mut self , block : & Block , _: ( ) ) {
99
103
100
- visit_block : |block, ( _, visitor) | {
101
- let old_unsafe_context = context. unsafe_context ;
104
+ let old_unsafe_context = self . context . unsafe_context ;
102
105
if block. rules == ast:: UnsafeBlock &&
103
- context. unsafe_context == SafeContext {
104
- context. unsafe_context = UnsafeBlock ( block. id )
106
+ self . context . unsafe_context == SafeContext {
107
+ self . context . unsafe_context = UnsafeBlock ( block. id )
105
108
}
106
109
107
- oldvisit :: visit_block ( block , ( ( ) , visitor ) ) ;
110
+ visit :: walk_block ( self , block , ( ) ) ;
108
111
109
- context. unsafe_context = old_unsafe_context
110
- } ,
112
+ self . context . unsafe_context = old_unsafe_context
113
+ }
114
+
115
+ fn visit_expr ( & mut self , expr : @expr, _: ( ) ) {
111
116
112
- visit_expr : |expr, ( _, visitor) | {
113
117
match expr. node {
114
118
expr_method_call( callee_id, _, _, _, _, _) => {
115
- let base_type = ty:: node_id_to_type ( tcx, callee_id) ;
119
+ let base_type = ty:: node_id_to_type ( self . tcx , callee_id) ;
116
120
debug ! ( "effect: method call case, base type is %s" ,
117
- ppaux:: ty_to_str( tcx, base_type) ) ;
121
+ ppaux:: ty_to_str( self . tcx, base_type) ) ;
118
122
if type_is_unsafe_function ( base_type) {
119
- require_unsafe ( expr. span ,
123
+ self . require_unsafe ( expr. span ,
120
124
"invocation of unsafe method" )
121
125
}
122
126
}
123
127
expr_call( base, _, _) => {
124
- let base_type = ty:: node_id_to_type ( tcx, base. id ) ;
128
+ let base_type = ty:: node_id_to_type ( self . tcx , base. id ) ;
125
129
debug ! ( "effect: call case, base type is %s" ,
126
- ppaux:: ty_to_str( tcx, base_type) ) ;
130
+ ppaux:: ty_to_str( self . tcx, base_type) ) ;
127
131
if type_is_unsafe_function ( base_type) {
128
- require_unsafe ( expr. span , "call to unsafe function" )
132
+ self . require_unsafe ( expr. span , "call to unsafe function" )
129
133
}
130
134
}
131
135
expr_unary( _, deref, base) => {
132
- let base_type = ty:: node_id_to_type ( tcx, base. id ) ;
136
+ let base_type = ty:: node_id_to_type ( self . tcx , base. id ) ;
133
137
debug ! ( "effect: unary case, base type is %s" ,
134
- ppaux:: ty_to_str( tcx, base_type) ) ;
138
+ ppaux:: ty_to_str( self . tcx, base_type) ) ;
135
139
match ty:: get ( base_type) . sty {
136
140
ty_ptr( _) => {
137
- require_unsafe ( expr. span ,
141
+ self . require_unsafe ( expr. span ,
138
142
"dereference of unsafe pointer" )
139
143
}
140
144
_ => { }
141
145
}
142
146
}
143
147
expr_inline_asm( * ) => {
144
- require_unsafe ( expr. span , "use of inline assembly" )
148
+ self . require_unsafe ( expr. span , "use of inline assembly" )
145
149
}
146
150
expr_path( * ) => {
147
- match ty:: resolve_expr ( tcx, expr) {
151
+ match ty:: resolve_expr ( self . tcx , expr) {
148
152
ast:: def_static( _, true ) => {
149
- require_unsafe ( expr. span , "use of mutable static" )
153
+ self . require_unsafe ( expr. span , "use of mutable static" )
150
154
}
151
155
_ => { }
152
156
}
153
157
}
154
158
_ => { }
155
159
}
156
160
157
- oldvisit:: visit_expr ( expr, ( ( ) , visitor) )
158
- } ,
161
+ visit:: walk_expr ( self , expr, ( ) ) ;
162
+ }
163
+ }
159
164
160
- .. * oldvisit:: default_visitor ( )
161
- } ) ;
165
+ pub fn check_crate ( tcx : ty:: ctxt ,
166
+ method_map : method_map ,
167
+ crate : & ast:: Crate ) {
168
+ let context = @mut Context {
169
+ method_map : method_map,
170
+ unsafe_context : SafeContext ,
171
+ } ;
172
+
173
+ let mut visitor = EffectCheckVisitor {
174
+ tcx : tcx,
175
+ context : context,
176
+ } ;
162
177
163
- oldvisit :: visit_crate ( crate , ( ( ) , visitor ) )
178
+ visit :: walk_crate ( & mut visitor , crate , ( ) ) ;
164
179
}
0 commit comments