Skip to content

Module export #340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 1, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 62 additions & 17 deletions src/comp/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ tag namespace {
ns_type;
}

// This indicates whether we're searching up the scope chain or whether we've
// found a path component and started following it back down, which has an
// effect on export visibility
tag direction {
up;
down;
}

type import_map = std.map.hashmap[ast.def_id,def_wrap];

// A simple wrapper over defs that stores a bit more information about modules
Expand Down Expand Up @@ -151,7 +159,7 @@ fn find_final_def(&env e, import_map index,
sess = e.sess);
auto tmp_e = update_env_for_item(empty_e, i);
auto next_i = rest_idents.(0);
auto next_ = lookup_name_wrapped(tmp_e, next_i, ns);
auto next_ = lookup_name_wrapped(tmp_e, next_i, ns, down);
alt (next_) {
case (none[tup(@env, def_wrap)]) {
e.sess.span_err(sp, "unresolved name: " + next_i);
Expand All @@ -172,10 +180,11 @@ fn find_final_def(&env e, import_map index,
-> def_wrap {
auto len = _vec.len[ident](idents);
auto rest_idents = _vec.slice[ident](idents, 1u, len);
auto empty_e = rec(scopes = nil[scope], sess = e.sess);
auto empty_e = rec(scopes = nil[scope],
sess = e.sess);
auto tmp_e = update_env_for_external_mod(empty_e, mod_id, idents);
auto next_i = rest_idents.(0);
auto next_ = lookup_name_wrapped(tmp_e, next_i, ns);
auto next_ = lookup_name_wrapped(tmp_e, next_i, ns, down);
alt (next_) {
case (none[tup(@env, def_wrap)]) {
e.sess.span_err(sp, "unresolved name: " + next_i);
Expand Down Expand Up @@ -270,7 +279,7 @@ fn find_final_def(&env e, import_map index,
index.insert(option.get[ast.def_id](import_id), def_wrap_resolving);
}
auto first = idents.(0);
auto d_ = lookup_name_wrapped(e, first, ns);
auto d_ = lookup_name_wrapped(e, first, ns, up);
alt (d_) {
case (none[tup(@env, def_wrap)]) {
e.sess.span_err(sp, "unresolved name: " + first);
Expand All @@ -286,8 +295,8 @@ fn find_final_def(&env e, import_map index,
}
}

fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
-> option.t[tup(@env, def_wrap)] {
fn lookup_name_wrapped(&env e, ast.ident i, namespace ns, direction dir)
-> option.t[tup(@env, def_wrap)] {

// log "resolving name " + i;

Expand Down Expand Up @@ -347,23 +356,59 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
fail;
}

fn check_mod(ast.ident i, ast._mod m, namespace ns)
-> option.t[def_wrap] {
fn check_mod(ast.ident i, ast._mod m, namespace ns,
direction dir) -> option.t[def_wrap] {

fn visible(ast.ident i, ast._mod m, direction dir) -> bool {

alt (dir) {
case (up) {
ret true;
}
case (down) {
// fall through
}
}

auto count = 0;
for (@ast.view_item vi in m.view_items) {
alt (vi.node) {
case (ast.view_item_export(?id)) {
if (_str.eq(i, id)) {
ret true;
}
count += 1;
}
case (_) { /* fall through */ }
}
}
// If there are no declared exports then everything is exported
if (count == 0) {
ret true;
} else {
ret false;
}
}

alt (m.index.find(i)) {
case (some[ast.mod_index_entry](?ent)) {
alt (ent) {
case (ast.mie_view_item(?view_item)) {
ret some(found_def_view(view_item));
}
case (ast.mie_item(?item)) {
ret some(found_def_item(item, ns));
if (visible(i, m, dir)) {
ret some(found_def_item(item, ns));
}
}
case (ast.mie_tag_variant(?item, ?variant_idx)) {
alt (item.node) {
case (ast.item_tag(_, ?variants, _, ?tid, _)) {
auto vid = variants.(variant_idx).node.id;
auto t = ast.def_variant(tid, vid);
ret some[def_wrap](def_wrap_other(t));
if (visible(i, m, dir)) {
auto vid = variants.(variant_idx).node.id;
auto t = ast.def_variant(tid, vid);
ret some[def_wrap](def_wrap_other(t));
}
}
case (_) {
log_err "tag item not actually a tag";
Expand Down Expand Up @@ -454,11 +499,11 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
}

fn in_scope(&session.session sess, ast.ident identifier, &scope s,
namespace ns) -> option.t[def_wrap] {
namespace ns, direction dir) -> option.t[def_wrap] {
alt (s) {

case (scope_crate(?c)) {
ret check_mod(identifier, c.node.module, ns);
ret check_mod(identifier, c.node.module, ns, dir);
}

case (scope_item(?it)) {
Expand Down Expand Up @@ -494,7 +539,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
}
}
case (ast.item_mod(_, ?m, _)) {
ret check_mod(identifier, m, ns);
ret check_mod(identifier, m, ns, dir);
}
case (ast.item_native_mod(_, ?m, _)) {
ret check_native_mod(identifier, m);
Expand Down Expand Up @@ -558,14 +603,14 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
ret none[tup(@env, def_wrap)];
}
case (cons[scope](?hd, ?tl)) {
auto x = in_scope(e.sess, i, hd, ns);
auto x = in_scope(e.sess, i, hd, ns, dir);
alt (x) {
case (some[def_wrap](?x)) {
ret some(tup(@e, x));
}
case (none[def_wrap]) {
auto outer_env = rec(scopes = *tl with e);
ret lookup_name_wrapped(outer_env, i, ns);
ret lookup_name_wrapped(outer_env, i, ns, up);
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/test/compile-fail/export-boot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// xfail-stage0
// error-pattern: unknown module item

// rustboot has a different error message than rustc
// this test can die with rustboot, or rustc's error can change

mod foo {
export x;
fn x(int y) {
log y;
}
fn z(int y) {
log y;
}
}

fn main() {
foo.z(10);
}
21 changes: 21 additions & 0 deletions src/test/compile-fail/export-fully-qualified.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// xfail-boot
// error-pattern: unresolved name

// In this test baz isn't resolved when called as foo.baz even though
// it's called from inside foo. This is somewhat surprising and may
// want to change eventually.

mod foo {

export bar;

fn bar() {
foo.baz();
}

fn baz() {
}
}

fn main() {
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/export-import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// xfail-boot
// error-pattern: unresolved name

import m.unexported;

mod m {
export exported;

fn exported() {
}

fn unexported() {
}
}


fn main() {
unexported();
}
17 changes: 17 additions & 0 deletions src/test/compile-fail/export-tag-variant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// xfail-boot
// error-pattern: unresolved name

mod foo {
export x;

fn x() {
}

tag y {
y1;
}
}

fn main() {
auto z = foo.y1;
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/export.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// xfail-stage0
// error-pattern: unknown module item
// xfail-boot
// error-pattern: unresolved name
mod foo {
export x;
fn x(int y) {
Expand Down
25 changes: 25 additions & 0 deletions src/test/compile-fail/export2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// xfail-boot
// error-pattern: unresolved name

mod foo {
export x;

fn x() {
bar.x();
}
}

mod bar {
export y;

fn x() {
log "x";
}

fn y() {
}
}

fn main() {
foo.x();
}
18 changes: 18 additions & 0 deletions src/test/run-pass/export-non-interference2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
mod foo {

export bar;

mod bar {
fn y() {
x();
}
}

fn x() {
log "x";
}
}

fn main() {
foo.bar.y();
}
19 changes: 19 additions & 0 deletions src/test/run-pass/export-non-interference3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
mod foo {
export x;

fn x() {
bar.x();
}
}

mod bar {
export x;

fn x() {
log "x";
}
}

fn main() {
foo.x();
}