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