@@ -3,20 +3,25 @@ import syntax::{visit, ast_util};
3
3
import driver:: session:: session;
4
4
import std:: map:: hashmap;
5
5
6
- fn check_crate ( sess : session , crate : @crate , def_map : resolve:: def_map ,
6
+ fn check_crate ( sess : session , crate : @crate , ast_map : ast_map:: map ,
7
+ def_map : resolve:: def_map ,
7
8
method_map : typeck:: method_map , tcx : ty:: ctxt ) {
8
9
visit:: visit_crate ( * crate , false , visit:: mk_vt ( @{
9
- visit_item: check_item,
10
+ visit_item: check_item ( sess , ast_map , def_map , _ , _ , _ ) ,
10
11
visit_pat: check_pat,
11
12
visit_expr: bind check_expr ( sess, def_map, method_map, tcx, _, _, _)
12
13
with * visit:: default_visitor ( )
13
14
} ) ) ;
14
15
sess. abort_if_errors ( ) ;
15
16
}
16
17
17
- fn check_item ( it : @item, &&_is_const : bool , v : visit:: vt < bool > ) {
18
+ fn check_item ( sess : session , ast_map : ast_map:: map , def_map : resolve:: def_map ,
19
+ it: @item, & & _is_const: bool , v : visit:: vt < bool > ) {
18
20
alt it. node {
19
- item_const ( _, ex) { v. visit_expr ( ex, true , v) ; }
21
+ item_const ( _, ex) {
22
+ v. visit_expr ( ex, true , v) ;
23
+ check_item_recursion ( sess, ast_map, def_map, it) ;
24
+ }
20
25
item_enum ( vs, _) {
21
26
for var in vs {
22
27
option:: with_option_do ( var. node . disr_expr ) { |ex|
@@ -73,7 +78,7 @@ fn check_expr(sess: session, def_map: resolve::def_map,
73
78
"` in a constant expression" ) ;
74
79
}
75
80
}
76
- expr_path ( path ) {
81
+ expr_path ( _ ) {
77
82
alt def_map. find ( e. id ) {
78
83
some ( def_const ( def_id) ) {
79
84
if !ast_util:: is_local ( def_id) {
@@ -115,6 +120,63 @@ fn check_expr(sess: session, def_map: resolve::def_map,
115
120
visit:: visit_expr ( e, is_const, v) ;
116
121
}
117
122
123
+ // Make sure a const item doesn't recursively refer to itself
124
+ // FIXME: Should use the dependency graph when it's available
125
+ fn check_item_recursion ( sess : session , ast_map : ast_map:: map ,
126
+ def_map : resolve:: def_map , it: @item) {
127
+
128
+ type env = {
129
+ root_it : @item,
130
+ sess : session ,
131
+ ast_map : ast_map:: map ,
132
+ def_map : resolve:: def_map ,
133
+ idstack : @mut [ node_id ] ,
134
+ } ;
135
+
136
+ let env = {
137
+ root_it: it,
138
+ sess: sess,
139
+ ast_map: ast_map,
140
+ def_map: def_map,
141
+ idstack: @mut [ ]
142
+ } ;
143
+
144
+ let visitor = visit:: mk_vt ( @{
145
+ visit_item: visit_item,
146
+ visit_expr: visit_expr
147
+ with * visit:: default_visitor ( )
148
+ } ) ;
149
+ visitor. visit_item ( it, env, visitor) ;
150
+
151
+ fn visit_item ( it : @item, &&env : env , v : visit:: vt < env > ) {
152
+ if ( * env. idstack ) . contains ( it. id ) {
153
+ env. sess . span_fatal ( env. root_it . span , "recursive constant" ) ;
154
+ }
155
+ vec:: push ( * env. idstack , it. id ) ;
156
+ visit:: visit_item ( it, env, v) ;
157
+ vec:: pop ( * env. idstack ) ;
158
+ }
159
+
160
+ fn visit_expr ( e : @expr, &&env : env , v : visit:: vt < env > ) {
161
+ alt e. node {
162
+ expr_path ( path) {
163
+ alt env. def_map . find ( e. id ) {
164
+ some ( def_const ( def_id) ) {
165
+ alt check env. ast_map . get ( def_id. node ) {
166
+ ast_map:: node_item ( it, _) {
167
+ v. visit_item ( it, env, v) ;
168
+ }
169
+ }
170
+ }
171
+ _ { }
172
+ }
173
+ }
174
+ _ { }
175
+ }
176
+ visit:: visit_expr ( e, env, v) ;
177
+ }
178
+ }
179
+
118
180
// Local Variables:
119
181
// mode: rust
120
182
// fill-column: 78;
0 commit comments