]> git.lizzy.rs Git - rust.git/commitdiff
item_like_imports: Allow single imports with a given visibility
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Fri, 19 Aug 2016 22:52:26 +0000 (22:52 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Thu, 1 Sep 2016 22:30:24 +0000 (22:30 +0000)
to reexport some (but not all) namespaces with less visibility.

src/librustc_resolve/resolve_imports.rs
src/test/compile-fail/imports/reexports.rs [new file with mode: 0644]

index c7cb3a351784dff8b6288314cfe656e13e6e2375..7084aa685aec5664f9ae6f79832c0aa77cc38b9c 100644 (file)
@@ -285,13 +285,20 @@ pub fn add_import_directive(&mut self,
     // return the corresponding binding defined by the import directive.
     fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
               -> NameBinding<'a> {
+        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
+                     !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
+            directive.vis.get()
+        } else {
+            binding.pseudo_vis()
+        };
+
         NameBinding {
             kind: NameBindingKind::Import {
                 binding: binding,
                 directive: directive,
             },
             span: directive.span,
-            vis: directive.vis.get(),
+            vis: vis,
         }
     }
 
@@ -597,22 +604,44 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
             }
         }
 
+        let session = self.session;
+        let reexport_error = || {
+            let msg = format!("`{}` is private, and cannot be reexported", name);
+            let note_msg =
+                format!("consider marking `{}` as `pub` in the imported module", name);
+            struct_span_err!(session, directive.span, E0364, "{}", &msg)
+                .span_note(directive.span, &note_msg)
+                .emit();
+        };
+
+        let extern_crate_lint = || {
+            let msg = format!("extern crate `{}` is private, and cannot be reexported \
+                               (error E0364), consider declaring with `pub`",
+                               name);
+            session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
+        };
+
         match (value_result, type_result) {
+            // With `#![feature(item_like_imports)]`, all namespaces
+            // must be re-exported with extra visibility for an error to occur.
+            (Ok(value_binding), Ok(type_binding)) if self.new_import_semantics => {
+                let vis = directive.vis.get();
+                if !value_binding.pseudo_vis().is_at_least(vis, self) &&
+                   !type_binding.pseudo_vis().is_at_least(vis, self) {
+                    reexport_error();
+                } else if type_binding.is_extern_crate() &&
+                          !type_binding.vis.is_at_least(vis, self) {
+                    extern_crate_lint();
+                }
+            }
+
             (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
-                let msg = format!("`{}` is private, and cannot be reexported", name);
-                let note_msg =
-                    format!("consider marking `{}` as `pub` in the imported module", name);
-                struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
-                    .span_note(directive.span, &note_msg)
-                    .emit();
+                reexport_error();
             }
 
             (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
                 if binding.is_extern_crate() {
-                    let msg = format!("extern crate `{}` is private, and cannot be reexported \
-                                       (error E0364), consider declaring with `pub`",
-                                       name);
-                    self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
+                    extern_crate_lint();
                 } else {
                     struct_span_err!(self.session, directive.span, E0365,
                                      "`{}` is private, and cannot be reexported", name)
diff --git a/src/test/compile-fail/imports/reexports.rs b/src/test/compile-fail/imports/reexports.rs
new file mode 100644 (file)
index 0000000..f8dbb4d
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 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.
+
+#![feature(item_like_imports)]
+
+mod a {
+    fn foo() {}
+    mod foo {}
+
+    mod a {
+        pub use super::foo; //~ ERROR cannot be reexported
+    }
+}
+
+mod b {
+    pub fn foo() {}
+    mod foo { pub struct S; }
+
+    pub mod a {
+        pub use super::foo; // This is OK since the value `foo` is visible enough.
+        fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` reexported).
+    }
+}
+
+mod c {
+    // Test that `foo` is not reexported.
+    use b::a::foo::S; //~ ERROR `foo`
+}
+
+fn main() {}