Skip to content

Commit

Permalink
Move capture checking into resolve.rs
Browse files Browse the repository at this point in the history
Drops capture.rs. The new algorithm also checks for captures function
arguments and obj fields.
  • Loading branch information
marijnh committed May 13, 2011
1 parent 89490e4 commit 58ec5d1
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 141 deletions.
3 changes: 0 additions & 3 deletions src/comp/driver/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 =
Expand Down
2 changes: 0 additions & 2 deletions src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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; }
Expand Down
119 changes: 0 additions & 119 deletions src/comp/middle/capture.rs

This file was deleted.

61 changes: 49 additions & 12 deletions src/comp/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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] {
Expand Down Expand Up @@ -441,15 +469,13 @@ 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, _, _)){
ret lookup_in_fn(id, decl, ty_params, ns);
}
}
}

case (scope_loop(?d)) {
if (ns == ns_value) {
alt (d.node) {
Expand All @@ -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);
Expand All @@ -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;
}
}
}
Expand Down Expand Up @@ -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 }
Expand Down
3 changes: 0 additions & 3 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 (_) {}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/comp/rustc.rc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ mod middle {
mod walk;
mod metadata;
mod resolve;
mod capture;
mod typeck;
mod typestate_check;
}
Expand Down
1 change: 0 additions & 1 deletion src/test/compile-fail/bad-env-capture.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// xfail-stage0
// xfail-stage1
// xfail-stage2
// error-pattern: attempted dynamic environment-capture
fn foo() {
let int x;
Expand Down
11 changes: 11 additions & 0 deletions src/test/compile-fail/bad-env-capture2.rs
Original file line number Diff line number Diff line change
@@ -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);
}
14 changes: 14 additions & 0 deletions src/test/compile-fail/bad-env-capture3.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 58ec5d1

Please sign in to comment.