diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 9e51e4428388..76738fe8737e 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -53,7 +53,7 @@ tag scope { scope_native_item(@ast::native_item); scope_loop(@ast::local); // there's only 1 decl per loop. - scope_block(ast::blk); + scope_block(ast::blk, @mutable uint, @mutable uint); scope_arm(ast::arm); } @@ -254,6 +254,7 @@ fn resolve_names(e: &@env, c: &@ast::crate) { @{visit_native_item: visit_native_item_with_scope, visit_item: visit_item_with_scope, visit_block: visit_block_with_scope, + visit_decl: visit_decl_with_scope, visit_arm: bind walk_arm(e, _, _, _), visit_pat: bind walk_pat(e, _, _, _), visit_expr: bind walk_expr(e, _, _, _), @@ -353,7 +354,30 @@ fn visit_fn_with_scope(e: &@env, f: &ast::_fn, tp: &[ast::ty_param], } fn visit_block_with_scope(b: &ast::blk, sc: &scopes, v: &vt[scopes]) { - visit::visit_block(b, cons(scope_block(b), @sc), v); + let pos = @mutable 0u, loc = @mutable 0u; + let block_sc = cons(scope_block(b, pos, loc), @sc); + for stmt in b.node.stmts { + v.visit_stmt(stmt, block_sc, v); + *pos += 1u; + *loc = 0u; + } + visit::visit_expr_opt(b.node.expr, block_sc, v); +} + +fn visit_decl_with_scope(d: &@decl, sc: &scopes, v: &vt[scopes]) { + let loc_pos = alt list::car(sc) { + scope_block(_, _, pos) { pos } + _ { @mutable 0u } + }; + alt d.node { + decl_local(locs) { + for loc in locs { + v.visit_local(loc, sc, v); + *loc_pos += 1u; + } + } + decl_item(it) { v.visit_item(it, sc, v); } + } } 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, } } } - scope_block(b) { ret lookup_in_block(name, b.node, ns); } + scope_block(b, pos, loc) { + ret lookup_in_block(name, b.node, *pos, *loc, ns); + } scope_arm(a) { if ns == ns_value { ret option::map(ast::def_binding, @@ -755,18 +781,26 @@ fn lookup_in_obj(name: &ident, ob: &ast::_obj, ty_params: &[ast::ty_param], } } -fn lookup_in_block(name: &ident, b: &ast::blk_, ns: namespace) -> - option::t[def] { - for st: @ast::stmt in b.stmts { +fn lookup_in_block(name: &ident, b: &ast::blk_, pos: uint, loc_pos: uint, + ns: namespace) -> option::t[def] { + let i = ivec::len(b.stmts); + while i > 0u { + i -= 1u; + let st = b.stmts.(i); alt st.node { ast::stmt_decl(d, _) { alt d.node { ast::decl_local(locs) { - for loc: @ast::local in locs { - if ns == ns_value { - alt lookup_in_pat(name, loc.node.pat) { - some(did) { ret some(ast::def_local(did)); } - _ {} + if i <= pos { + let j = ivec::len(locs); + while j > 0u { + j -= 1u; + let loc = locs.(j); + if ns == ns_value && (i < pos || j < loc_pos) { + alt lookup_in_pat(name, loc.node.pat) { + some(did) { ret some(ast::def_local(did)); } + _ {} + } } } } @@ -1272,8 +1306,13 @@ fn check_block(e: &@env, b: &ast::blk, x: &(), v: &vt[()]) { ast::stmt_decl(d, _) { alt d.node { ast::decl_local(locs) { - for loc: @ast::local in locs { - check_pat(values, loc.node.pat); + let local_values = checker(*e, "value"); + for loc in locs { + for each p in ast::pat_bindings(loc.node.pat) { + let ident = alt p.node { pat_bind(n) { n } }; + add_name(local_values, p.span, ident); + check_name(values, p.span, ident); + } } } ast::decl_item(it) { @@ -1339,12 +1378,15 @@ fn checker(e: &env, kind: str) -> checker { ret @{mutable seen: seen, kind: kind, sess: e.sess}; } -fn add_name(ch: &checker, sp: &span, name: &ident) { +fn check_name(ch: &checker, sp: &span, name: &ident) { for s: ident in ch.seen { if str::eq(s, name) { ch.sess.span_fatal(sp, "duplicate " + ch.kind + " name: " + name); } } +} +fn add_name(ch: &checker, sp: &span, name: &ident) { + check_name(ch, sp, name); ch.seen += ~[name]; } diff --git a/src/test/compile-fail/alt-join.rs b/src/test/compile-fail/alt-join.rs index bbd4ac5c73aa..613e1e123827 100644 --- a/src/test/compile-fail/alt-join.rs +++ b/src/test/compile-fail/alt-join.rs @@ -1,12 +1,10 @@ -// error-pattern:Unsatisfied precondition constraint +// error-pattern:unresolved name // a good test that we merge paths correctly in the presence of a // variable that's used before it's declared -// should be rejected by typestate because we use x without initializing it fn my_fail() -> ! { fail; } fn main() { - alt (true) { false { my_fail(); } true {} diff --git a/src/test/compile-fail/capture1.rs b/src/test/compile-fail/capture1.rs index 24232933ddea..1e8e48aea028 100644 --- a/src/test/compile-fail/capture1.rs +++ b/src/test/compile-fail/capture1.rs @@ -3,8 +3,6 @@ // error-pattern: attempted dynamic environment-capture fn main() { - - fn foo() -> int { ret bar; } - let bar: int = 5; + fn foo() -> int { ret bar; } } \ No newline at end of file diff --git a/src/test/compile-fail/duplicate-name.rs b/src/test/compile-fail/duplicate-name.rs deleted file mode 100644 index 294d782f916a..000000000000 --- a/src/test/compile-fail/duplicate-name.rs +++ /dev/null @@ -1,3 +0,0 @@ -// error-pattern: duplicate value name: x - -fn main() { let x = 10; let x: int = 20; } \ No newline at end of file diff --git a/src/test/compile-fail/occurs-check-2.rs b/src/test/compile-fail/occurs-check-2.rs index 9b5536e57c36..20a4cf314c48 100644 --- a/src/test/compile-fail/occurs-check-2.rs +++ b/src/test/compile-fail/occurs-check-2.rs @@ -1,5 +1,6 @@ // error-pattern: Type inference failed because I could not find fn main() { - let f = @f; + let f; + f = @f; f(); } \ No newline at end of file diff --git a/src/test/compile-fail/occurs-check-3.rs b/src/test/compile-fail/occurs-check-3.rs index f0439b87aed8..74a2328f107c 100644 --- a/src/test/compile-fail/occurs-check-3.rs +++ b/src/test/compile-fail/occurs-check-3.rs @@ -1,4 +1,4 @@ // error-pattern:mismatched types // From Issue #778 tag clam[T] { a(T); } -fn main() { let c = a(c); alt c { a[int](_) { } } } +fn main() { let c; c = a(c); alt c { a[int](_) { } } } diff --git a/src/test/compile-fail/occurs-check.rs b/src/test/compile-fail/occurs-check.rs index a2bd12fcc354..16b2f94045e9 100644 --- a/src/test/compile-fail/occurs-check.rs +++ b/src/test/compile-fail/occurs-check.rs @@ -1,4 +1,5 @@ // error-pattern: Type inference failed because I could not find fn main() { - let f = @f; + let f; + f = @f; } diff --git a/src/test/compile-fail/shadow.rs b/src/test/run-pass/shadow.rs similarity index 69% rename from src/test/compile-fail/shadow.rs rename to src/test/run-pass/shadow.rs index 3576a1e4ded8..238723b32bc1 100644 --- a/src/test/compile-fail/shadow.rs +++ b/src/test/run-pass/shadow.rs @@ -1,5 +1,4 @@ // -*- rust -*- -// error-pattern:src/test/compile-fail/shadow.rs fn foo(c: [int]) { let a: int = 5; let b: [int] = ~[]; @@ -7,9 +6,15 @@ fn foo(c: [int]) { alt none[int] { some[int](_) { for i: int in c { log a; let a = 17; b += ~[a]; } } + _ {} } } tag t[T] { none; some(T); } -fn main() { foo(~[]); } +fn main() { + let x = 10; + let x = x + 20; + assert x == 30; + foo(~[]); +}