Skip to content

Commit 58ec5d1

Browse files
committed
Move capture checking into resolve.rs
Drops capture.rs. The new algorithm also checks for captures function arguments and obj fields.
1 parent 89490e4 commit 58ec5d1

File tree

9 files changed

+74
-141
lines changed

9 files changed

+74
-141
lines changed

src/comp/driver/rustc.rs

-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import front::eval;
77
import front::ast;
88
import middle::trans;
99
import middle::resolve;
10-
import middle::capture;
1110
import middle::ty;
1211
import middle::typeck;
1312
import middle::typestate_check;
@@ -94,8 +93,6 @@ fn compile_input(session::session sess,
9493
bind creader::read_crates(sess, crate));
9594
auto def_map = time(time_passes, "resolution",
9695
bind resolve::resolve_crate(sess, crate));
97-
time[()](time_passes, "capture checking",
98-
bind capture::check_for_captures(sess, crate, def_map));
9996

10097
auto ty_cx = ty::mk_ctxt(sess, def_map);
10198
auto typeck_result =

src/comp/front/ast.rs

-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ tag def {
4646
def_const(def_id);
4747
def_arg(def_id);
4848
def_local(def_id);
49-
def_upvar(def_id);
5049
def_variant(def_id /* tag */, def_id /* variant */);
5150
def_ty(def_id);
5251
def_ty_arg(uint);
@@ -74,7 +73,6 @@ fn def_id_of_def(def d) -> def_id {
7473
case (def_const(?id)) { ret id; }
7574
case (def_arg(?id)) { ret id; }
7675
case (def_local(?id)) { ret id; }
77-
case (def_upvar(?id)) { ret id; }
7876
case (def_variant(_, ?id)) { ret id; }
7977
case (def_ty(?id)) { ret id; }
8078
case (def_ty_arg(_)) { fail; }

src/comp/middle/capture.rs

-119
This file was deleted.

src/comp/middle/resolve.rs

+49-12
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ fn resolve_import(&env e, &@ast::view_item it, &list[scope] sc) {
317317

318318
if (n_idents == 1u) {
319319
register(e, defid, it.span, end_id,
320-
lookup_in_scope(e, sc, end_id, ns_value),
321-
lookup_in_scope(e, sc, end_id, ns_type));
320+
lookup_in_scope(e, sc, it.span, end_id, ns_value),
321+
lookup_in_scope(e, sc, it.span, end_id, ns_type));
322322
} else {
323323
auto dcur = lookup_in_scope_strict(e, sc, it.span, ids.(0), ns_value);
324324
auto i = 1u;
@@ -394,7 +394,7 @@ fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
394394

395395
fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
396396
namespace ns) -> def {
397-
alt (lookup_in_scope(e, sc, id, ns)) {
397+
alt (lookup_in_scope(e, sc, sp, id, ns)) {
398398
case (none[def]) {
399399
unresolved(e, sp, id, ns_name(ns));
400400
fail;
@@ -405,7 +405,35 @@ fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
405405
}
406406
}
407407

408-
fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
408+
fn scope_is_fn(&scope sc) -> bool {
409+
ret alt (sc) {
410+
case (scope_item(?it)) {
411+
alt (it.node) {
412+
case (ast::item_fn(_, _, _, _, _)) { true }
413+
case (_) { false }
414+
}
415+
}
416+
case (scope_native_item(_)) { true }
417+
case (_) { false }
418+
};
419+
}
420+
421+
fn def_is_local(&def d) -> bool {
422+
ret alt (d) {
423+
case (ast::def_arg(_)) { true }
424+
case (ast::def_local(_)) { true }
425+
case (ast::def_binding(_)) { true }
426+
case (_) { false }
427+
};
428+
}
429+
fn def_is_obj_field(&def d) -> bool {
430+
ret alt (d) {
431+
case (ast::def_obj_field(_)) { true }
432+
case (_) { false }
433+
};
434+
}
435+
436+
fn lookup_in_scope(&env e, list[scope] sc, &span sp, ident id, namespace ns)
409437
-> option::t[def] {
410438
fn in_scope(&env e, ident id, &scope s, namespace ns)
411439
-> option::t[def] {
@@ -441,15 +469,13 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
441469
case (_) {}
442470
}
443471
}
444-
445472
case (scope_native_item(?it)) {
446473
alt (it.node) {
447474
case (ast::native_item_fn(_, _, ?decl, ?ty_params, _, _)){
448475
ret lookup_in_fn(id, decl, ty_params, ns);
449476
}
450477
}
451478
}
452-
453479
case (scope_loop(?d)) {
454480
if (ns == ns_value) {
455481
alt (d.node) {
@@ -461,11 +487,9 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
461487
}
462488
}
463489
}
464-
465490
case (scope_block(?b)) {
466491
ret lookup_in_block(id, b.node, ns);
467492
}
468-
469493
case (scope_arm(?a)) {
470494
if (ns == ns_value) {
471495
ret lookup_in_pat(id, *a.pat);
@@ -475,16 +499,30 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
475499
ret none[def];
476500
}
477501

502+
auto left_fn = false;
503+
// Used to determine whether obj fields are in scope
504+
auto left_fn_level2 = false;
478505
while (true) {
479506
alt (sc) {
480507
case (nil[scope]) {
481508
ret none[def];
482509
}
483510
case (cons[scope](?hd, ?tl)) {
484-
alt (in_scope(e, id, hd, ns)) {
485-
case (some[def](?x)) { ret some(x); }
486-
case (_) { sc = *tl; }
511+
auto fnd = in_scope(e, id, hd, ns);
512+
if (fnd != none[def]) {
513+
auto df = option::get(fnd);
514+
if ((left_fn && def_is_local(df)) ||
515+
(left_fn_level2 && def_is_obj_field(df))) {
516+
e.sess.span_err(sp, "attempted dynamic " +
517+
"environment-capture");
518+
}
519+
ret fnd;
520+
}
521+
if (left_fn) { left_fn_level2 = true; }
522+
if (ns == ns_value && !left_fn) {
523+
left_fn = scope_is_fn(hd);
487524
}
525+
sc = *tl;
488526
}
489527
}
490528
}
@@ -841,7 +879,6 @@ fn check_def_by_ns(def d, namespace ns) -> bool {
841879
case (ast::def_const(?id)) { ns == ns_value }
842880
case (ast::def_arg(?id)) { ns == ns_value }
843881
case (ast::def_local(?id)) { ns == ns_value }
844-
case (ast::def_upvar(?id)) { ns == ns_value }
845882
case (ast::def_variant(_, ?id)) { ns == ns_value }
846883
case (ast::def_ty(?id)) { ns == ns_type }
847884
case (ast::def_binding(?id)) { ns == ns_type }

src/comp/middle/trans.rs

-3
Original file line numberDiff line numberDiff line change
@@ -3807,9 +3807,6 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
38073807
case (ast::def_local(?did)) {
38083808
_vec::push[ast::def_id](e.refs, did);
38093809
}
3810-
case (ast::def_upvar(?did)) {
3811-
_vec::push[ast::def_id](e.refs, did);
3812-
}
38133810
case (_) {}
38143811
}
38153812
}

src/comp/rustc.rc

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ mod middle {
1717
mod walk;
1818
mod metadata;
1919
mod resolve;
20-
mod capture;
2120
mod typeck;
2221
mod typestate_check;
2322
}

src/test/compile-fail/bad-env-capture.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// xfail-stage0
22
// xfail-stage1
3-
// xfail-stage2
43
// error-pattern: attempted dynamic environment-capture
54
fn foo() {
65
let int x;
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// xfail-stage0
2+
// xfail-stage1
3+
// error-pattern: attempted dynamic environment-capture
4+
fn foo(int x) {
5+
fn bar() {
6+
log x;
7+
}
8+
}
9+
fn main() {
10+
foo(2);
11+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// xfail-stage0
2+
// xfail-stage1
3+
// error-pattern: attempted dynamic environment-capture
4+
obj foo(int x) {
5+
fn mth() {
6+
fn bar() {
7+
log x;
8+
}
9+
}
10+
}
11+
12+
fn main() {
13+
foo(2);
14+
}

0 commit comments

Comments
 (0)