mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
rustc: Implement explicit global scope resolution via leading "::"; add a test case
This commit is contained in:
parent
99a95b3613
commit
05390b4b38
@ -228,7 +228,8 @@ fn mk_test_desc_rec(&test_ctxt cx, ast::ident[] path) -> @ast::expr {
|
||||
ident = "name",
|
||||
expr = @name_expr));
|
||||
|
||||
let ast::path fn_path = nospan(rec(idents = path,
|
||||
let ast::path fn_path = nospan(rec(global = false,
|
||||
idents = path,
|
||||
types = ~[]));
|
||||
|
||||
let ast::expr fn_expr = rec(id = cx.next_node_id(),
|
||||
@ -280,7 +281,8 @@ fn mk_main(&test_ctxt cx) -> @ast::item {
|
||||
|
||||
fn mk_test_main_call(&test_ctxt cx) -> @ast::expr {
|
||||
|
||||
let ast::path test_path = nospan(rec(idents = ~["tests"],
|
||||
let ast::path test_path = nospan(rec(global = false,
|
||||
idents = ~["tests"],
|
||||
types = ~[]));
|
||||
|
||||
let ast::expr_ test_path_expr_ = ast::expr_path(test_path);
|
||||
@ -295,7 +297,8 @@ fn mk_test_main_call(&test_ctxt cx) -> @ast::expr {
|
||||
node = test_call_expr_,
|
||||
span = rec(lo=0u, hi=0u));
|
||||
|
||||
let ast::path test_main_path = nospan(rec(idents = ~["std",
|
||||
let ast::path test_main_path = nospan(rec(global = false,
|
||||
idents = ~["std",
|
||||
"test",
|
||||
"test_main"],
|
||||
types = ~[]));
|
||||
|
@ -91,7 +91,7 @@ fn parse_path(@pstate st, str_def sd) -> ast::path {
|
||||
case (?c) {
|
||||
if (c == '(') {
|
||||
ret respan(rec(lo=0u, hi=0u),
|
||||
rec(idents=idents, types=~[]));
|
||||
rec(global=false, idents=idents, types=~[]));
|
||||
}
|
||||
else {
|
||||
idents += ~[parse_ident_(st, sd, is_last)];
|
||||
|
@ -44,7 +44,7 @@ export def_map;
|
||||
// (FIXME See https://github.com/graydon/rust/issues/358 for the reason this
|
||||
// isn't a const.)
|
||||
tag scope {
|
||||
scope_crate(@ast::crate);
|
||||
scope_crate;
|
||||
scope_item(@ast::item);
|
||||
scope_fn(ast::fn_decl, ast::ty_param[]);
|
||||
scope_native_item(@ast::native_item);
|
||||
@ -154,7 +154,7 @@ fn map_crate(&@env e, &@ast::crate c) {
|
||||
@rec(visit_view_item=bind index_vi(e, _, _, _),
|
||||
visit_item=bind index_i(e, _, _, _)
|
||||
with *visit::default_visitor[scopes]());
|
||||
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
||||
visit::visit_crate(*c, cons(scope_crate, @nil),
|
||||
visit::mk_vt(v_map_mod));
|
||||
// Register the top-level mod
|
||||
|
||||
@ -199,7 +199,7 @@ fn map_crate(&@env e, &@ast::crate c) {
|
||||
@rec(visit_view_item=bind link_glob(e, _, _, _),
|
||||
visit_item=visit_item_with_scope
|
||||
with *visit::default_visitor[scopes]());
|
||||
visit::visit_crate(*c, cons(scope_crate(c), @nil),
|
||||
visit::visit_crate(*c, cons(scope_crate, @nil),
|
||||
visit::mk_vt(v_link_glob));
|
||||
fn link_glob(@env e, &@ast::view_item vi, &scopes sc, &vt[scopes] v) {
|
||||
fn find_mod(@env e, scopes sc) -> @indexed_mod {
|
||||
@ -253,7 +253,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
|
||||
visit_constr=bind walk_constr(e, _, _, _),
|
||||
visit_fn=bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
|
||||
with *visit::default_visitor());
|
||||
visit::visit_crate(*c, cons(scope_crate(c), @nil), visit::mk_vt(v));
|
||||
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v));
|
||||
e.sess.abort_if_errors();
|
||||
|
||||
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
|
||||
@ -261,8 +261,8 @@ fn resolve_names(&@env e, &@ast::crate c) {
|
||||
alt (exp.node) {
|
||||
case (ast::expr_path(?p)) {
|
||||
maybe_insert(e, exp.id,
|
||||
lookup_path_strict(*e, sc, exp.span,
|
||||
p.node.idents, ns_value));
|
||||
lookup_path_strict(*e, sc, exp.span, p.node,
|
||||
ns_value));
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
@ -272,16 +272,16 @@ fn resolve_names(&@env e, &@ast::crate c) {
|
||||
alt (t.node) {
|
||||
case (ast::ty_path(?p, ?id)) {
|
||||
maybe_insert(e, id,
|
||||
lookup_path_strict(*e, sc, t.span,
|
||||
p.node.idents, ns_type));
|
||||
lookup_path_strict(*e, sc, t.span, p.node,
|
||||
ns_type));
|
||||
}
|
||||
case (_) { }
|
||||
}
|
||||
}
|
||||
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
|
||||
maybe_insert(e, c.node.id,
|
||||
lookup_path_strict(*e, sc, c.span,
|
||||
c.node.path.node.idents, ns_value));
|
||||
lookup_path_strict(*e, sc, c.span, c.node.path.node,
|
||||
ns_value));
|
||||
}
|
||||
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
|
||||
for (@ast::pat p in a.pats) { walk_pat(*e, sc, p); }
|
||||
@ -291,8 +291,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
|
||||
alt (pat.node) {
|
||||
case (ast::pat_tag(?p, ?children)) {
|
||||
auto fnd =
|
||||
lookup_path_strict(e, sc, p.span, p.node.idents,
|
||||
ns_value);
|
||||
lookup_path_strict(e, sc, p.span, p.node, ns_value);
|
||||
if (option::is_some(fnd)) {
|
||||
alt (option::get(fnd)) {
|
||||
case (ast::def_variant(?did, ?vid)) {
|
||||
@ -396,7 +395,7 @@ fn follow_import(&env e, &scopes sc, &ident[] path, &span sp)
|
||||
fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
|
||||
&vt[scopes] v) {
|
||||
auto new_def =
|
||||
lookup_path_strict(*e, sc, c.span, c.node.path.node.idents, ns_value);
|
||||
lookup_path_strict(*e, sc, c.span, c.node.path.node, ns_value);
|
||||
if (option::is_some(new_def)) {
|
||||
alt (option::get(new_def)) {
|
||||
case (ast::def_fn(?pred_id, ast::pure_fn)) {
|
||||
@ -543,16 +542,26 @@ fn mk_unresolved_msg(&ident id, &str kind) -> str {
|
||||
}
|
||||
|
||||
// Lookup helpers
|
||||
fn lookup_path_strict(&env e, &scopes sc, &span sp, &ident[] idents,
|
||||
fn lookup_path_strict(&env e, &scopes sc, &span sp, &ast::path_ pth,
|
||||
namespace ns) -> option::t[def] {
|
||||
auto n_idents = ivec::len(idents);
|
||||
auto n_idents = ivec::len(pth.idents);
|
||||
auto headns = if (n_idents == 1u) { ns } else { ns_module };
|
||||
auto dcur = lookup_in_scope_strict(e, sc, sp, idents.(0), headns);
|
||||
|
||||
auto first_scope;
|
||||
if (pth.global) {
|
||||
first_scope = list::cons(scope_crate, @list::nil);
|
||||
} else {
|
||||
first_scope = sc;
|
||||
}
|
||||
|
||||
auto dcur = lookup_in_scope_strict(e, first_scope, sp, pth.idents.(0),
|
||||
headns);
|
||||
|
||||
auto i = 1u;
|
||||
while (i < n_idents && option::is_some(dcur)) {
|
||||
auto curns = if (n_idents == i + 1u) { ns } else { ns_module };
|
||||
dcur = lookup_in_mod_strict(e, option::get(dcur),
|
||||
sp, idents.(i), curns, outside);
|
||||
sp, pth.idents.(i), curns, outside);
|
||||
i += 1u;
|
||||
}
|
||||
ret dcur;
|
||||
@ -592,7 +601,7 @@ fn lookup_in_scope(&env e, scopes sc, &span sp, &ident name, namespace ns) ->
|
||||
fn in_scope(&env e, &span sp, &ident name, &scope s, namespace ns) ->
|
||||
option::t[def] {
|
||||
alt (s) {
|
||||
case (scope_crate(?c)) {
|
||||
case (scope_crate) {
|
||||
ret lookup_in_local_mod(e, -1, sp, name, ns, inside);
|
||||
}
|
||||
case (scope_item(?it)) {
|
||||
|
@ -16,7 +16,7 @@ type fn_ident = option::t[ident];
|
||||
// FIXME: with typestate constraint, could say
|
||||
// idents and types are the same length, and are
|
||||
// non-empty
|
||||
type path_ = rec(ident[] idents, (@ty)[] types);
|
||||
type path_ = rec(bool global, ident[] idents, (@ty)[] types);
|
||||
|
||||
type path = spanned[path_];
|
||||
|
||||
|
@ -63,7 +63,7 @@ fn pieces_to_expr(&ext_ctxt cx, span sp, vec[piece] pieces,
|
||||
}
|
||||
fn make_path_expr(&ext_ctxt cx, span sp, &ast::ident[] idents)
|
||||
-> @ast::expr {
|
||||
auto path = rec(idents=idents, types=~[]);
|
||||
auto path = rec(global=false, idents=idents, types=~[]);
|
||||
auto sp_path = rec(node=path, span=sp);
|
||||
auto pathexpr = ast::expr_path(sp_path);
|
||||
ret @rec(id=cx.next_id(), node=pathexpr, span=sp);
|
||||
|
@ -499,7 +499,8 @@ fn noop_fold_ident(&ident i, ast_fold fld) -> ident {
|
||||
}
|
||||
|
||||
fn noop_fold_path(&path_ p, ast_fold fld) -> path_ {
|
||||
ret rec(idents=ivec::map(fld.fold_ident, p.idents),
|
||||
ret rec(global=p.global,
|
||||
idents=ivec::map(fld.fold_ident, p.idents),
|
||||
types=ivec::map(fld.fold_ty, p.types));
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,8 @@ fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
|
||||
auto hi = p.get_hi_pos();
|
||||
ret @spanned(lo, hi,
|
||||
ast::ty_path(spanned(lo, hi,
|
||||
rec(idents=pth.node.idents,
|
||||
rec(global=pth.node.global,
|
||||
idents=pth.node.idents,
|
||||
types=seq_ivec)),
|
||||
ann));
|
||||
}
|
||||
@ -556,7 +557,7 @@ fn parse_ty(&parser p) -> @ast::ty {
|
||||
auto typ = parse_ty(p);
|
||||
t = typ.node;
|
||||
hi = typ.span.hi;
|
||||
} else if (is_ident(p.peek())) {
|
||||
} else if (p.peek() == token::MOD_SEP || is_ident(p.peek())) {
|
||||
auto path = parse_path(p);
|
||||
t = ast::ty_path(path, p.get_id());
|
||||
hi = path.span.hi;
|
||||
@ -673,6 +674,14 @@ fn is_ident(token::token t) -> bool {
|
||||
fn parse_path(&parser p) -> ast::path {
|
||||
auto lo = p.get_lo_pos();
|
||||
auto hi = lo;
|
||||
|
||||
auto global;
|
||||
if (p.peek() == token::MOD_SEP) {
|
||||
global = true; p.bump();
|
||||
} else {
|
||||
global = false;
|
||||
}
|
||||
|
||||
let ast::ident[] ids = ~[];
|
||||
while (true) {
|
||||
alt (p.peek()) {
|
||||
@ -686,7 +695,7 @@ fn parse_path(&parser p) -> ast::path {
|
||||
}
|
||||
}
|
||||
hi = p.get_hi_pos();
|
||||
ret spanned(lo, hi, rec(idents=ids, types=~[]));
|
||||
ret spanned(lo, hi, rec(global=global, idents=ids, types=~[]));
|
||||
}
|
||||
|
||||
fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
|
||||
@ -701,7 +710,9 @@ fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
|
||||
for (@ast::ty typ in seq.node) { seq_ivec += ~[typ]; }
|
||||
|
||||
auto hi = p.get_hi_pos();
|
||||
path = spanned(lo, hi, rec(idents=path.node.idents, types=seq_ivec));
|
||||
path = spanned(lo, hi, rec(global=path.node.global,
|
||||
idents=path.node.idents,
|
||||
types=seq_ivec));
|
||||
}
|
||||
ret path;
|
||||
}
|
||||
@ -975,8 +986,9 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
|
||||
parse_expr, p);
|
||||
hi = es.span.hi;
|
||||
ex = ast::expr_call(f, es.node);
|
||||
} else if (is_ident(p.peek()) && !is_word(p, "true") &&
|
||||
!is_word(p, "false")) {
|
||||
} else if (p.peek() == token::MOD_SEP ||
|
||||
(is_ident(p.peek()) && !is_word(p, "true") &&
|
||||
!is_word(p, "false"))) {
|
||||
check_bad_word(p);
|
||||
auto pth = parse_path_and_ty_param_substs(p);
|
||||
hi = pth.span.hi;
|
||||
|
14
src/test/run-pass/global-scope.rs
Normal file
14
src/test/run-pass/global-scope.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// xfail-stage0
|
||||
|
||||
fn f() -> int { ret 1; }
|
||||
|
||||
mod foo {
|
||||
fn f() -> int { ret 2; }
|
||||
fn g() {
|
||||
assert (f() == 2);
|
||||
assert (::f() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { ret foo::g(); }
|
||||
|
Loading…
Reference in New Issue
Block a user