Skip to content

Commit e33af7e

Browse files
committed
Make let bindings' scope start at their definition
Also, allow let bindings in a block to shadow each other.
1 parent 92719e4 commit e33af7e

File tree

8 files changed

+70
-28
lines changed

8 files changed

+70
-28
lines changed

src/comp/middle/resolve.rs

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ tag scope {
5353
scope_native_item(@ast::native_item);
5454
scope_loop(@ast::local); // there's only 1 decl per loop.
5555

56-
scope_block(ast::blk);
56+
scope_block(ast::blk, @mutable uint, @mutable uint);
5757
scope_arm(ast::arm);
5858
}
5959

@@ -254,6 +254,7 @@ fn resolve_names(e: &@env, c: &@ast::crate) {
254254
@{visit_native_item: visit_native_item_with_scope,
255255
visit_item: visit_item_with_scope,
256256
visit_block: visit_block_with_scope,
257+
visit_decl: visit_decl_with_scope,
257258
visit_arm: bind walk_arm(e, _, _, _),
258259
visit_pat: bind walk_pat(e, _, _, _),
259260
visit_expr: bind walk_expr(e, _, _, _),
@@ -353,7 +354,30 @@ fn visit_fn_with_scope(e: &@env, f: &ast::_fn, tp: &[ast::ty_param],
353354
}
354355

355356
fn visit_block_with_scope(b: &ast::blk, sc: &scopes, v: &vt[scopes]) {
356-
visit::visit_block(b, cons(scope_block(b), @sc), v);
357+
let pos = @mutable 0u, loc = @mutable 0u;
358+
let block_sc = cons(scope_block(b, pos, loc), @sc);
359+
for stmt in b.node.stmts {
360+
v.visit_stmt(stmt, block_sc, v);
361+
*pos += 1u;
362+
*loc = 0u;
363+
}
364+
visit::visit_expr_opt(b.node.expr, block_sc, v);
365+
}
366+
367+
fn visit_decl_with_scope(d: &@decl, sc: &scopes, v: &vt[scopes]) {
368+
let loc_pos = alt list::car(sc) {
369+
scope_block(_, _, pos) { pos }
370+
_ { @mutable 0u }
371+
};
372+
alt d.node {
373+
decl_local(locs) {
374+
for loc in locs {
375+
v.visit_local(loc, sc, v);
376+
*loc_pos += 1u;
377+
}
378+
}
379+
decl_item(it) { v.visit_item(it, sc, v); }
380+
}
357381
}
358382

359383
fn visit_arm_with_scope(a: &ast::arm, sc: &scopes, v: &vt[scopes]) {
@@ -650,7 +674,9 @@ fn lookup_in_scope(e: &env, sc: scopes, sp: &span, name: &ident,
650674
}
651675
}
652676
}
653-
scope_block(b) { ret lookup_in_block(name, b.node, ns); }
677+
scope_block(b, pos, loc) {
678+
ret lookup_in_block(name, b.node, *pos, *loc, ns);
679+
}
654680
scope_arm(a) {
655681
if ns == ns_value {
656682
ret option::map(ast::def_binding,
@@ -755,18 +781,26 @@ fn lookup_in_obj(name: &ident, ob: &ast::_obj, ty_params: &[ast::ty_param],
755781
}
756782
}
757783

758-
fn lookup_in_block(name: &ident, b: &ast::blk_, ns: namespace) ->
759-
option::t[def] {
760-
for st: @ast::stmt in b.stmts {
784+
fn lookup_in_block(name: &ident, b: &ast::blk_, pos: uint, loc_pos: uint,
785+
ns: namespace) -> option::t[def] {
786+
let i = ivec::len(b.stmts);
787+
while i > 0u {
788+
i -= 1u;
789+
let st = b.stmts.(i);
761790
alt st.node {
762791
ast::stmt_decl(d, _) {
763792
alt d.node {
764793
ast::decl_local(locs) {
765-
for loc: @ast::local in locs {
766-
if ns == ns_value {
767-
alt lookup_in_pat(name, loc.node.pat) {
768-
some(did) { ret some(ast::def_local(did)); }
769-
_ {}
794+
if i <= pos {
795+
let j = ivec::len(locs);
796+
while j > 0u {
797+
j -= 1u;
798+
let loc = locs.(j);
799+
if ns == ns_value && (i < pos || j < loc_pos) {
800+
alt lookup_in_pat(name, loc.node.pat) {
801+
some(did) { ret some(ast::def_local(did)); }
802+
_ {}
803+
}
770804
}
771805
}
772806
}
@@ -1272,8 +1306,13 @@ fn check_block(e: &@env, b: &ast::blk, x: &(), v: &vt[()]) {
12721306
ast::stmt_decl(d, _) {
12731307
alt d.node {
12741308
ast::decl_local(locs) {
1275-
for loc: @ast::local in locs {
1276-
check_pat(values, loc.node.pat);
1309+
let local_values = checker(*e, "value");
1310+
for loc in locs {
1311+
for each p in ast::pat_bindings(loc.node.pat) {
1312+
let ident = alt p.node { pat_bind(n) { n } };
1313+
add_name(local_values, p.span, ident);
1314+
check_name(values, p.span, ident);
1315+
}
12771316
}
12781317
}
12791318
ast::decl_item(it) {
@@ -1339,12 +1378,15 @@ fn checker(e: &env, kind: str) -> checker {
13391378
ret @{mutable seen: seen, kind: kind, sess: e.sess};
13401379
}
13411380

1342-
fn add_name(ch: &checker, sp: &span, name: &ident) {
1381+
fn check_name(ch: &checker, sp: &span, name: &ident) {
13431382
for s: ident in ch.seen {
13441383
if str::eq(s, name) {
13451384
ch.sess.span_fatal(sp, "duplicate " + ch.kind + " name: " + name);
13461385
}
13471386
}
1387+
}
1388+
fn add_name(ch: &checker, sp: &span, name: &ident) {
1389+
check_name(ch, sp, name);
13481390
ch.seen += ~[name];
13491391
}
13501392

src/test/compile-fail/alt-join.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
// error-pattern:Unsatisfied precondition constraint
1+
// error-pattern:unresolved name
22
// a good test that we merge paths correctly in the presence of a
33
// variable that's used before it's declared
4-
// should be rejected by typestate because we use x without initializing it
54

65
fn my_fail() -> ! { fail; }
76

87
fn main() {
9-
108
alt (true) {
119
false { my_fail(); }
1210
true {}

src/test/compile-fail/capture1.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// error-pattern: attempted dynamic environment-capture
44

55
fn main() {
6-
7-
fn foo() -> int { ret bar; }
8-
96
let bar: int = 5;
7+
fn foo() -> int { ret bar; }
108
}

src/test/compile-fail/duplicate-name.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// error-pattern: Type inference failed because I could not find
22
fn main() {
3-
let f = @f;
3+
let f;
4+
f = @f;
45
f();
56
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// error-pattern:mismatched types
22
// From Issue #778
33
tag clam[T] { a(T); }
4-
fn main() { let c = a(c); alt c { a[int](_) { } } }
4+
fn main() { let c; c = a(c); alt c { a[int](_) { } } }

src/test/compile-fail/occurs-check.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// error-pattern: Type inference failed because I could not find
22
fn main() {
3-
let f = @f;
3+
let f;
4+
f = @f;
45
}
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
// -*- rust -*-
2-
// error-pattern:src/test/compile-fail/shadow.rs
32
fn foo(c: [int]) {
43
let a: int = 5;
54
let b: [int] = ~[];
65

76

87
alt none[int] {
98
some[int](_) { for i: int in c { log a; let a = 17; b += ~[a]; } }
9+
_ {}
1010
}
1111
}
1212

1313
tag t[T] { none; some(T); }
1414

15-
fn main() { foo(~[]); }
15+
fn main() {
16+
let x = 10;
17+
let x = x + 20;
18+
assert x == 30;
19+
foo(~[]);
20+
}

0 commit comments

Comments
 (0)