aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarijn Haverbeke <[email protected]>2011-05-13 11:57:58 +0200
committerMarijn Haverbeke <[email protected]>2011-05-13 12:44:05 +0200
commit58ec5d1654f367d7f3459ebee2b5f4c89e0f3aa1 (patch)
tree803ad4b840000f5af60041d6c565f210f12bf7a1
parentChange resolve to use walk instead of fold (diff)
downloadrust-58ec5d1654f367d7f3459ebee2b5f4c89e0f3aa1.tar.xz
rust-58ec5d1654f367d7f3459ebee2b5f4c89e0f3aa1.zip
Move capture checking into resolve.rs
Drops capture.rs. The new algorithm also checks for captures function arguments and obj fields.
-rw-r--r--src/comp/driver/rustc.rs3
-rw-r--r--src/comp/front/ast.rs2
-rw-r--r--src/comp/middle/capture.rs119
-rw-r--r--src/comp/middle/resolve.rs61
-rw-r--r--src/comp/middle/trans.rs3
-rw-r--r--src/comp/rustc.rc1
-rw-r--r--src/test/compile-fail/bad-env-capture.rs1
-rw-r--r--src/test/compile-fail/bad-env-capture2.rs11
-rw-r--r--src/test/compile-fail/bad-env-capture3.rs14
9 files changed, 74 insertions, 141 deletions
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index ad89ac9c..6592c23a 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -7,7 +7,6 @@ import front::eval;
import front::ast;
import middle::trans;
import middle::resolve;
-import middle::capture;
import middle::ty;
import middle::typeck;
import middle::typestate_check;
@@ -94,8 +93,6 @@ fn compile_input(session::session sess,
bind creader::read_crates(sess, crate));
auto def_map = time(time_passes, "resolution",
bind resolve::resolve_crate(sess, crate));
- time[()](time_passes, "capture checking",
- bind capture::check_for_captures(sess, crate, def_map));
auto ty_cx = ty::mk_ctxt(sess, def_map);
auto typeck_result =
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index c107e7c8..5e5185bf 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -46,7 +46,6 @@ tag def {
def_const(def_id);
def_arg(def_id);
def_local(def_id);
- def_upvar(def_id);
def_variant(def_id /* tag */, def_id /* variant */);
def_ty(def_id);
def_ty_arg(uint);
@@ -74,7 +73,6 @@ fn def_id_of_def(def d) -> def_id {
case (def_const(?id)) { ret id; }
case (def_arg(?id)) { ret id; }
case (def_local(?id)) { ret id; }
- case (def_upvar(?id)) { ret id; }
case (def_variant(_, ?id)) { ret id; }
case (def_ty(?id)) { ret id; }
case (def_ty_arg(_)) { fail; }
diff --git a/src/comp/middle/capture.rs b/src/comp/middle/capture.rs
deleted file mode 100644
index 7124554a..00000000
--- a/src/comp/middle/capture.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-import driver::session;
-import front::ast;
-import std::map::hashmap;
-import std::option;
-import std::option::some;
-import std::option::none;
-import std::_int;
-import std::_vec;
-import util::common;
-import resolve::def_map;
-
-type fn_id_of_local = std::map::hashmap[ast::def_id, ast::def_id];
-type env = rec(mutable vec[ast::def_id] current_context, // fn or obj
- def_map def_map,
- fn_id_of_local idmap,
- session::session sess);
-
-fn current_context(&env e) -> ast::def_id {
- ret e.current_context.(_vec::len(e.current_context) - 1u);
-}
-
-fn enter_item(@env e, &@ast::item i) {
- alt (i.node) {
- case (ast::item_fn(?name, _, _, ?id, _)) {
- _vec::push(e.current_context, id);
- }
- case (ast::item_obj(?name, _, _, ?ids, _)) {
- _vec::push(e.current_context, ids.ty);
- }
- case (_) {}
- }
-}
-
-fn leave_item(@env e, &@ast::item i) {
- alt (i.node) {
- case (ast::item_fn(?name, _, _, ?id, _)) {
- _vec::pop(e.current_context);
- }
- case (ast::item_obj(_, _, _, ?ids, _)) {
- _vec::pop(e.current_context);
- }
- case (_) {}
- }
-}
-
-fn walk_expr(@env e, &@ast::expr x) {
- alt (x.node) {
- case (ast::expr_for(?d, _, _, _)) {
- alt (d.node) {
- case (ast::decl_local(?local)) {
- e.idmap.insert(local.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (ast::expr_for_each(?d, _, _, _)) {
- alt (d.node) {
- case (ast::decl_local(?local)) {
- e.idmap.insert(local.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (ast::expr_path(?pt, ?ann)) {
- auto local_id;
- alt (e.def_map.get(ast::ann_tag(ann))) {
- case (ast::def_local(?id)) { local_id = id; }
- case (_) { ret; }
- }
- auto df = ast::def_id_of_def(e.def_map.get(ast::ann_tag(ann)));
- auto def_context = e.idmap.get(df);
-
- if (current_context(*e) != def_context) {
- e.sess.span_err(x.span,
- "attempted dynamic environment-capture");
- }
- }
- case (_) { }
- }
-}
-
-fn walk_block(@env e, &ast::block b) {
- for (@ast::stmt st in b.node.stmts) {
- alt (st.node) {
- case (ast::stmt_decl(?d,_)) {
- alt (d.node) {
- case (ast::decl_local(?loc)) {
- e.idmap.insert(loc.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (_) { }
- }
- }
-}
-
-fn check_for_captures(session::session sess, @ast::crate crate, def_map dm) {
- let vec[ast::def_id] curctx = vec();
- auto env = @rec(mutable current_context = curctx,
- def_map = dm,
- idmap = common::new_def_hash[ast::def_id](),
- sess = sess);
- auto visitor = rec(visit_item_pre = bind enter_item(env, _),
- visit_item_post = bind leave_item(env, _),
- visit_block_pre = bind walk_block(env, _),
- visit_expr_pre = bind walk_expr(env, _)
- with walk::default_visitor());
- walk::walk_crate(visitor, *crate);
-}
-
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
-// End:
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index ce7a2376..11837033 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -317,8 +317,8 @@ fn resolve_import(&env e, &@ast::view_item it, &list[scope] sc) {
if (n_idents == 1u) {
register(e, defid, it.span, end_id,
- lookup_in_scope(e, sc, end_id, ns_value),
- lookup_in_scope(e, sc, end_id, ns_type));
+ lookup_in_scope(e, sc, it.span, end_id, ns_value),
+ lookup_in_scope(e, sc, it.span, end_id, ns_type));
} else {
auto dcur = lookup_in_scope_strict(e, sc, it.span, ids.(0), ns_value);
auto i = 1u;
@@ -394,7 +394,7 @@ fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
namespace ns) -> def {
- alt (lookup_in_scope(e, sc, id, ns)) {
+ alt (lookup_in_scope(e, sc, sp, id, ns)) {
case (none[def]) {
unresolved(e, sp, id, ns_name(ns));
fail;
@@ -405,7 +405,35 @@ fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
}
}
-fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
+fn scope_is_fn(&scope sc) -> bool {
+ ret alt (sc) {
+ case (scope_item(?it)) {
+ alt (it.node) {
+ case (ast::item_fn(_, _, _, _, _)) { true }
+ case (_) { false }
+ }
+ }
+ case (scope_native_item(_)) { true }
+ case (_) { false }
+ };
+}
+
+fn def_is_local(&def d) -> bool {
+ ret alt (d) {
+ case (ast::def_arg(_)) { true }
+ case (ast::def_local(_)) { true }
+ case (ast::def_binding(_)) { true }
+ case (_) { false }
+ };
+}
+fn def_is_obj_field(&def d) -> bool {
+ ret alt (d) {
+ case (ast::def_obj_field(_)) { true }
+ case (_) { false }
+ };
+}
+
+fn lookup_in_scope(&env e, list[scope] sc, &span sp, ident id, namespace ns)
-> option::t[def] {
fn in_scope(&env e, ident id, &scope s, namespace ns)
-> option::t[def] {
@@ -441,7 +469,6 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
case (_) {}
}
}
-
case (scope_native_item(?it)) {
alt (it.node) {
case (ast::native_item_fn(_, _, ?decl, ?ty_params, _, _)){
@@ -449,7 +476,6 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
}
}
}
-
case (scope_loop(?d)) {
if (ns == ns_value) {
alt (d.node) {
@@ -461,11 +487,9 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
}
}
}
-
case (scope_block(?b)) {
ret lookup_in_block(id, b.node, ns);
}
-
case (scope_arm(?a)) {
if (ns == ns_value) {
ret lookup_in_pat(id, *a.pat);
@@ -475,16 +499,30 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
ret none[def];
}
+ auto left_fn = false;
+ // Used to determine whether obj fields are in scope
+ auto left_fn_level2 = false;
while (true) {
alt (sc) {
case (nil[scope]) {
ret none[def];
}
case (cons[scope](?hd, ?tl)) {
- alt (in_scope(e, id, hd, ns)) {
- case (some[def](?x)) { ret some(x); }
- case (_) { sc = *tl; }
+ auto fnd = in_scope(e, id, hd, ns);
+ if (fnd != none[def]) {
+ auto df = option::get(fnd);
+ if ((left_fn && def_is_local(df)) ||
+ (left_fn_level2 && def_is_obj_field(df))) {
+ e.sess.span_err(sp, "attempted dynamic " +
+ "environment-capture");
+ }
+ ret fnd;
+ }
+ if (left_fn) { left_fn_level2 = true; }
+ if (ns == ns_value && !left_fn) {
+ left_fn = scope_is_fn(hd);
}
+ sc = *tl;
}
}
}
@@ -841,7 +879,6 @@ fn check_def_by_ns(def d, namespace ns) -> bool {
case (ast::def_const(?id)) { ns == ns_value }
case (ast::def_arg(?id)) { ns == ns_value }
case (ast::def_local(?id)) { ns == ns_value }
- case (ast::def_upvar(?id)) { ns == ns_value }
case (ast::def_variant(_, ?id)) { ns == ns_value }
case (ast::def_ty(?id)) { ns == ns_type }
case (ast::def_binding(?id)) { ns == ns_type }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 78a7a16a..d822be17 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3807,9 +3807,6 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
case (ast::def_local(?did)) {
_vec::push[ast::def_id](e.refs, did);
}
- case (ast::def_upvar(?did)) {
- _vec::push[ast::def_id](e.refs, did);
- }
case (_) {}
}
}
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 0d011eee..ca5534b3 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -17,7 +17,6 @@ mod middle {
mod walk;
mod metadata;
mod resolve;
- mod capture;
mod typeck;
mod typestate_check;
}
diff --git a/src/test/compile-fail/bad-env-capture.rs b/src/test/compile-fail/bad-env-capture.rs
index 55fa7473..fa1e1d08 100644
--- a/src/test/compile-fail/bad-env-capture.rs
+++ b/src/test/compile-fail/bad-env-capture.rs
@@ -1,6 +1,5 @@
// xfail-stage0
// xfail-stage1
-// xfail-stage2
// error-pattern: attempted dynamic environment-capture
fn foo() {
let int x;
diff --git a/src/test/compile-fail/bad-env-capture2.rs b/src/test/compile-fail/bad-env-capture2.rs
new file mode 100644
index 00000000..ccec3310
--- /dev/null
+++ b/src/test/compile-fail/bad-env-capture2.rs
@@ -0,0 +1,11 @@
+// xfail-stage0
+// xfail-stage1
+// error-pattern: attempted dynamic environment-capture
+fn foo(int x) {
+ fn bar() {
+ log x;
+ }
+}
+fn main() {
+ foo(2);
+} \ No newline at end of file
diff --git a/src/test/compile-fail/bad-env-capture3.rs b/src/test/compile-fail/bad-env-capture3.rs
new file mode 100644
index 00000000..77f7881d
--- /dev/null
+++ b/src/test/compile-fail/bad-env-capture3.rs
@@ -0,0 +1,14 @@
+// xfail-stage0
+// xfail-stage1
+// error-pattern: attempted dynamic environment-capture
+obj foo(int x) {
+ fn mth() {
+ fn bar() {
+ log x;
+ }
+ }
+}
+
+fn main() {
+ foo(2);
+}