Skip to content

Commit 9aa7241

Browse files
committed
rustc: Don't allow recursive constants
1 parent 38ed2ea commit 9aa7241

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

src/rustc/driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
149149
time(time_passes, "typechecking",
150150
bind typeck::check_crate(ty_cx, impl_map, crate));
151151
time(time_passes, "const checking",
152-
bind middle::check_const::check_crate(sess, crate, def_map,
152+
bind middle::check_const::check_crate(sess, crate, ast_map, def_map,
153153
method_map, ty_cx));
154154

155155
if upto == cu_typeck { ret {crate: crate, tcx: some(ty_cx)}; }

src/rustc/middle/check_const.rs

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@ import syntax::{visit, ast_util};
33
import driver::session::session;
44
import std::map::hashmap;
55

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,
78
method_map: typeck::method_map, tcx: ty::ctxt) {
89
visit::visit_crate(*crate, false, visit::mk_vt(@{
9-
visit_item: check_item,
10+
visit_item: check_item(sess, ast_map, def_map, _, _, _),
1011
visit_pat: check_pat,
1112
visit_expr: bind check_expr(sess, def_map, method_map, tcx, _, _, _)
1213
with *visit::default_visitor()
1314
}));
1415
sess.abort_if_errors();
1516
}
1617

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>) {
1820
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+
}
2025
item_enum(vs, _) {
2126
for var in vs {
2227
option::with_option_do(var.node.disr_expr) {|ex|
@@ -73,7 +78,7 @@ fn check_expr(sess: session, def_map: resolve::def_map,
7378
"` in a constant expression");
7479
}
7580
}
76-
expr_path(path) {
81+
expr_path(_) {
7782
alt def_map.find(e.id) {
7883
some(def_const(def_id)) {
7984
if !ast_util::is_local(def_id) {
@@ -115,6 +120,63 @@ fn check_expr(sess: session, def_map: resolve::def_map,
115120
visit::visit_expr(e, is_const, v);
116121
}
117122

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+
118180
// Local Variables:
119181
// mode: rust
120182
// fill-column: 78;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// error-pattern: recursive constant
2+
const a: int = b;
3+
const b: int = a;
4+
5+
fn main() {
6+
}

0 commit comments

Comments
 (0)