]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Disallow importing through use statements
authorAlex Crichton <alex@alexcrichton.com>
Tue, 8 Apr 2014 21:31:25 +0000 (14:31 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 10 Apr 2014 22:22:00 +0000 (15:22 -0700)
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

src/libnative/io/file_win32.rs
src/librustc/front/test.rs
src/librustc/middle/resolve.rs
src/test/auxiliary/issue-12612-1.rs [new file with mode: 0644]
src/test/auxiliary/issue-12612-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-12612.rs [new file with mode: 0644]
src/test/run-pass/issue-11881.rs
src/test/run-pass/issue-12612.rs [new file with mode: 0644]

index 8090042f090c9aa7e53f616660bc68a8c65917b0..de515659bf7adc3c87d94899a92191f5f5aaf8c4 100644 (file)
@@ -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) };
index 86d2e039505f186f1a3e51435773e69e887fb07d..dff3d8b03bcbf6709f843c14da5050a92ed9ceb7 100644 (file)
@@ -297,20 +297,22 @@ fn main() {
 
 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
     }
 }
index 95101dc63371aa118a043f66c75ae0b5b2df48e0..cfacf0ee3df979edf0de24178afa370959e8e730 100644 (file)
@@ -2286,10 +2286,12 @@ fn resolve_single_import(&mut self,
             }
             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 @@ fn resolve_single_import(&mut self,
                                                           .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 @@ fn get_binding(this: &mut Resolver,
                                     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 @@ fn get_binding(this: &mut Resolver,
                                        .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 @@ fn resolve_module_path_from_root(&mut self,
             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 @@ fn resolve_item_in_lexical_scope(&mut self,
             match self.resolve_name_in_module(search_module,
                                               name,
                                               namespace,
-                                              PathSearch) {
+                                              PathSearch,
+                                              true) {
                 Failed => {
                     // Continue up the search chain.
                 }
@@ -3141,7 +3150,8 @@ fn resolve_name_in_module(&mut self,
                               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 @@ fn resolve_name_in_module(&mut self,
 
         // 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 @@ fn resolve_name_in_module(&mut self,
                     }
                 }
             }
-            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 (file)
index 0000000..a0234c1
--- /dev/null
@@ -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 (file)
index 0000000..b4ae437
--- /dev/null
@@ -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 (file)
index 0000000..9d6eb42
--- /dev/null
@@ -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() {}
+
index 2bf846fe3419ca59e0d586e3124c31fe07ac1b8f..7e51c6ad2aebbe2cd1679392047a5a13c884816d 100644 (file)
@@ -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 (file)
index 0000000..fcb6580
--- /dev/null
@@ -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() {}