about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-04-08 14:31:25 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-04-10 15:22:00 -0700
commit83d2c0b8a6f6c2ce25fe48b541f176ea88be8d99 (patch)
treec3fe31457b4a636e8ff9745f5a86fb5734677fa7
parent0bf4e900d421f011d7c68016308aab4998f9084e (diff)
downloadrust-83d2c0b8a6f6c2ce25fe48b541f176ea88be8d99.tar.gz
rust-83d2c0b8a6f6c2ce25fe48b541f176ea88be8d99.zip
rustc: Disallow importing through use statements
Resolve is currently erroneously allowing imports through private `use`
statements in some circumstances, even across module boundaries. For example,
this code compiles successfully today:

    use std::c_str;
    mod test {
        use c_str::CString;
    }

This should not be allowed because it was explicitly decided that private `use`
statements are purely bringing local names into scope, they are not
participating further in name resolution.

As a consequence of this patch, this code, while valid today, is now invalid:

    mod test {
        use std::c_str;

        unsafe fn foo() {
            ::test::c_str::CString::new(0 as *u8, false);
        }
    }

While plausibly acceptable, I found it to be more consistent if private imports
were only considered candidates to resolve the first component in a path, and no
others.

Closes #12612
-rw-r--r--src/libnative/io/file_win32.rs2
-rw-r--r--src/librustc/front/test.rs14
-rw-r--r--src/librustc/middle/resolve.rs22
-rw-r--r--src/test/auxiliary/issue-12612-1.rs13
-rw-r--r--src/test/auxiliary/issue-12612-2.rs11
-rw-r--r--src/test/compile-fail/issue-12612.rs24
-rw-r--r--src/test/run-pass/issue-11881.rs10
-rw-r--r--src/test/run-pass/issue-12612.rs23
8 files changed, 101 insertions, 18 deletions
diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs
index 8090042f090..de515659bf7 100644
--- a/src/libnative/io/file_win32.rs
+++ b/src/libnative/io/file_win32.rs
@@ -324,7 +324,7 @@ pub fn mkdir(p: &CString, _mode: io::FilePermission) -> IoResult<()> {
 }
 
 pub fn readdir(p: &CString) -> IoResult<Vec<Path>> {
-    use rt::global_heap::malloc_raw;
+    use std::rt::global_heap::malloc_raw;
 
     fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
         let root = unsafe { CString::new(root.with_ref(|p| p), false) };
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 86d2e039505..dff3d8b03bc 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -297,20 +297,22 @@ mod __test {
 
 fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
     let id_test = token::str_to_ident("test");
-    let vi = if cx.is_test_crate {
-        ast::ViewItemUse(
+    let (vi, vis) = if cx.is_test_crate {
+        (ast::ViewItemUse(
             vec!(@nospan(ast::ViewPathSimple(id_test,
                                              path_node(vec!(id_test)),
-                                             ast::DUMMY_NODE_ID))))
+                                             ast::DUMMY_NODE_ID)))),
+         ast::Public)
     } else {
-        ast::ViewItemExternCrate(id_test,
+        (ast::ViewItemExternCrate(id_test,
                                with_version("test"),
-                               ast::DUMMY_NODE_ID)
+                               ast::DUMMY_NODE_ID),
+         ast::Inherited)
     };
     ast::ViewItem {
         node: vi,
         attrs: Vec::new(),
-        vis: ast::Inherited,
+        vis: vis,
         span: DUMMY_SP
     }
 }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 95101dc6337..cfacf0ee3df 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -2286,10 +2286,12 @@ impl<'a> Resolver<'a> {
             }
             Some(child_name_bindings) => {
                 if child_name_bindings.defined_in_namespace(ValueNS) {
+                    debug!("(resolving single import) found value binding");
                     value_result = BoundResult(containing_module,
                                                *child_name_bindings);
                 }
                 if child_name_bindings.defined_in_namespace(TypeNS) {
+                    debug!("(resolving single import) found type binding");
                     type_result = BoundResult(containing_module,
                                               *child_name_bindings);
                 }
@@ -2320,6 +2322,7 @@ impl<'a> Resolver<'a> {
                                                           .borrow();
                 match import_resolutions.find(&source.name) {
                     None => {
+                        debug!("(resolving single import) no import");
                         // The containing module definitely doesn't have an
                         // exported import with the name in question. We can
                         // therefore accurately report that the names are
@@ -2353,6 +2356,8 @@ impl<'a> Resolver<'a> {
                                     return UnboundResult;
                                 }
                                 Some(target) => {
+                                    debug!("(resolving single import) found \
+                                            import in ns {:?}", namespace);
                                     let id = import_resolution.id(namespace);
                                     this.used_imports.insert((id, namespace));
                                     return BoundResult(target.target_module,
@@ -2396,6 +2401,8 @@ impl<'a> Resolver<'a> {
                                        .find_copy(&source.name) {
                     None => {} // Continue.
                     Some(module) => {
+                        debug!("(resolving single import) found external \
+                                module");
                         let name_bindings =
                             @Resolver::create_name_bindings_from_module(
                                 module);
@@ -2669,7 +2676,8 @@ impl<'a> Resolver<'a> {
             match self.resolve_name_in_module(search_module,
                                               name,
                                               TypeNS,
-                                              name_search_type) {
+                                              name_search_type,
+                                              false) {
                 Failed => {
                     let segment_name = token::get_ident(name);
                     let module_name = self.module_to_str(search_module);
@@ -2977,7 +2985,8 @@ impl<'a> Resolver<'a> {
             match self.resolve_name_in_module(search_module,
                                               name,
                                               namespace,
-                                              PathSearch) {
+                                              PathSearch,
+                                              true) {
                 Failed => {
                     // Continue up the search chain.
                 }
@@ -3141,7 +3150,8 @@ impl<'a> Resolver<'a> {
                               module_: @Module,
                               name: Ident,
                               namespace: Namespace,
-                              name_search_type: NameSearchType)
+                              name_search_type: NameSearchType,
+                              allow_private_imports: bool)
                               -> ResolveResult<(Target, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                token::get_ident(name),
@@ -3172,7 +3182,9 @@ impl<'a> Resolver<'a> {
 
         // Check the list of resolved imports.
         match module_.import_resolutions.borrow().find(&name.name) {
-            Some(import_resolution) => {
+            Some(import_resolution) if allow_private_imports ||
+                                       import_resolution.is_public.get() => {
+
                 if import_resolution.is_public.get() &&
                         import_resolution.outstanding_references.get() != 0 {
                     debug!("(resolving name in module) import \
@@ -3193,7 +3205,7 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
-            None => {} // Continue.
+            Some(..) | None => {} // Continue.
         }
 
         // Finally, search through external children.
diff --git a/src/test/auxiliary/issue-12612-1.rs b/src/test/auxiliary/issue-12612-1.rs
new file mode 100644
index 00000000000..a0234c1185a
--- /dev/null
+++ b/src/test/auxiliary/issue-12612-1.rs
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod bar {
+    pub fn foo() {}
+}
diff --git a/src/test/auxiliary/issue-12612-2.rs b/src/test/auxiliary/issue-12612-2.rs
new file mode 100644
index 00000000000..b4ae4374b2e
--- /dev/null
+++ b/src/test/auxiliary/issue-12612-2.rs
@@ -0,0 +1,11 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn baz() {}
diff --git a/src/test/compile-fail/issue-12612.rs b/src/test/compile-fail/issue-12612.rs
new file mode 100644
index 00000000000..9d6eb425678
--- /dev/null
+++ b/src/test/compile-fail/issue-12612.rs
@@ -0,0 +1,24 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-12612-1.rs
+
+extern crate foo = "issue-12612-1";
+
+use foo::bar;
+
+mod test {
+    use bar::foo;
+    //~^ ERROR: unresolved import
+    //~^^ ERROR: failed to resolve import
+}
+
+fn main() {}
+
diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs
index 2bf846fe341..7e51c6ad2ae 100644
--- a/src/test/run-pass/issue-11881.rs
+++ b/src/test/run-pass/issue-11881.rs
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate ser = "serialize";
+extern crate serialize;
 
-use serialize = self::ser;
- //necessary for deriving(Encodable)
-use ser::{Encodable, Encoder};
-use ser::json;
-use ser::ebml::writer;
+use serialize::{Encodable, Encoder};
+use serialize::json;
+use serialize::ebml::writer;
 use std::io::MemWriter;
 use std::str::from_utf8_owned;
 
diff --git a/src/test/run-pass/issue-12612.rs b/src/test/run-pass/issue-12612.rs
new file mode 100644
index 00000000000..fcb658036b6
--- /dev/null
+++ b/src/test/run-pass/issue-12612.rs
@@ -0,0 +1,23 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-12612-1.rs
+// aux-build:issue-12612-2.rs
+
+extern crate foo = "issue-12612-1";
+extern crate bar = "issue-12612-2";
+
+use foo::bar;
+
+mod test {
+    use bar::baz;
+}
+
+fn main() {}