about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-11-29 11:20:49 -0800
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-12-05 17:23:01 -0800
commit58e80400b24c09624ee602746c80d25aa18e0c86 (patch)
tree3772eb1d7e0f314794119d9ac1614527afb57831
parent8503b3ff822c1ed01c89773d30e4e10b886d77a5 (diff)
downloadrust-58e80400b24c09624ee602746c80d25aa18e0c86.tar.gz
rust-58e80400b24c09624ee602746c80d25aa18e0c86.zip
Include non-`pub` `use` and `extern crate` items in the crate metadata for macros 2.0.
-rw-r--r--src/librustc/hir/def.rs4
-rw-r--r--src/librustc/ich/impls_hir.rs1
-rw-r--r--src/librustc/ty/mod.rs9
-rw-r--r--src/librustc_metadata/cstore_impl.rs6
-rw-r--r--src/librustc_metadata/decoder.rs17
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_privacy/lib.rs13
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs8
-rw-r--r--src/librustc_resolve/lib.rs12
-rw-r--r--src/librustc_resolve/macros.rs8
-rw-r--r--src/librustc_resolve/resolve_imports.rs10
-rw-r--r--src/test/run-pass/hygiene/auxiliary/xcrate.rs38
-rw-r--r--src/test/run-pass/hygiene/xcrate.rs21
13 files changed, 126 insertions, 25 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 64bcdc7920a..a82c2f08463 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -14,6 +14,7 @@ use syntax::ast;
 use syntax::ext::base::MacroKind;
 use syntax_pos::Span;
 use hir;
+use ty;
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum CtorKind {
@@ -126,6 +127,9 @@ pub struct Export {
     pub def: Def,
     /// The span of the target definition.
     pub span: Span,
+    /// The visibility of the export.
+    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
+    pub vis: ty::Visibility,
 }
 
 impl CtorKind {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 77bf3da679d..a02efe7bd86 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -1162,6 +1162,7 @@ for hir::def_id::DefIndex {
 impl_stable_hash_for!(struct hir::def::Export {
     ident,
     def,
+    vis,
     span
 });
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index afe999cede7..93ef29855ce 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -307,6 +307,15 @@ impl Visibility {
 
         self.is_accessible_from(vis_restriction, tree)
     }
+
+    // Returns true if this item is visible anywhere in the local crate.
+    pub fn is_visible_locally(self) -> bool {
+        match self {
+            Visibility::Public => true,
+            Visibility::Restricted(def_id) => def_id.is_local(),
+            Visibility::Invisible => false,
+        }
+    }
 }
 
 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 911b4dac4e1..bcf749da8cd 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -305,12 +305,12 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
                 let mut add_child = |bfs_queue: &mut VecDeque<_>,
                                      child: &def::Export,
                                      parent: DefId| {
-                    let child = child.def.def_id();
-
-                    if tcx.visibility(child) != ty::Visibility::Public {
+                    if child.vis != ty::Visibility::Public {
                         return;
                     }
 
+                    let child = child.def.def_id();
+
                     match visible_parent_map.entry(child) {
                         Entry::Occupied(mut entry) => {
                             // If `child` is defined in crate `cnum`, ensure
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index eb2bcfc93c5..e2ad5fbf22b 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -631,7 +631,12 @@ impl<'a, 'tcx> CrateMetadata {
                         ext.kind()
                     );
                     let ident = Ident::with_empty_ctxt(name);
-                    callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
+                    callback(def::Export {
+                        ident: ident,
+                        def: def,
+                        vis: ty::Visibility::Public,
+                        span: DUMMY_SP,
+                    });
                 }
             }
             return
@@ -668,6 +673,7 @@ impl<'a, 'tcx> CrateMetadata {
                                 callback(def::Export {
                                     def,
                                     ident: Ident::from_str(&self.item_name(child_index)),
+                                    vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                 });
                             }
@@ -685,7 +691,8 @@ impl<'a, 'tcx> CrateMetadata {
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
                     let ident = Ident::from_str(&name);
-                    callback(def::Export { def: def, ident: ident, span: span });
+                    let vis = self.get_visibility(child_index);
+                    callback(def::Export { def, ident, vis, span });
                     // For non-reexport structs and variants add their constructors to children.
                     // Reexport lists automatically contain constructors when necessary.
                     match def {
@@ -693,7 +700,8 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
                                 let ctor_kind = self.get_ctor_kind(child_index);
                                 let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
-                                callback(def::Export { def: ctor_def, ident: ident, span: span });
+                                let vis = self.get_visibility(ctor_def_id.index);
+                                callback(def::Export { def: ctor_def, ident, vis, span });
                             }
                         }
                         Def::Variant(def_id) => {
@@ -701,7 +709,8 @@ impl<'a, 'tcx> CrateMetadata {
                             // value namespace, they are reserved for possible future use.
                             let ctor_kind = self.get_ctor_kind(child_index);
                             let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-                            callback(def::Export { def: ctor_def, ident: ident, span: span });
+                            let vis = self.get_visibility(child_index);
+                            callback(def::Export { def: ctor_def, ident, vis, span });
                         }
                         _ => {}
                     }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 6cfa324797c..7de3b8a4264 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -506,9 +506,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
         let data = ModData {
             reexports: match tcx.module_exports(def_id) {
-                Some(ref exports) if *vis == hir::Public => {
-                    self.lazy_seq_from_slice(exports.as_slice())
-                }
+                Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
                 _ => LazySeq::empty(),
             },
         };
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 74d92ce1c3e..27898b5dd64 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -331,7 +331,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             if let Some(exports) = self.tcx.module_exports(def_id) {
                 for export in exports.iter() {
                     if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
-                        self.update(node_id, Some(AccessLevel::Exported));
+                        if export.vis == ty::Visibility::Public {
+                            self.update(node_id, Some(AccessLevel::Exported));
+                        }
                     }
                 }
             }
@@ -365,6 +367,15 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             for id in &module.item_ids {
                 self.update(id.id, level);
             }
+            let def_id = self.tcx.hir.local_def_id(module_id);
+            if let Some(exports) = self.tcx.module_exports(def_id) {
+                for export in exports.iter() {
+                    if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
+                        self.update(node_id, level);
+                    }
+                }
+            }
+
             if module_id == ast::CRATE_NODE_ID {
                 break
             }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index afca6ea2c07..f19c1998d10 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -466,11 +466,8 @@ impl<'a> Resolver<'a> {
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
-        let ident = child.ident;
-        let def = child.def;
+        let Export { ident, def, vis, span } = child;
         let def_id = def.def_id();
-        let vis = self.cstore.visibility_untracked(def_id);
-        let span = child.span;
         let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
         match def {
             Def::Mod(..) | Def::Enum(..) => {
@@ -674,7 +671,8 @@ impl<'a> Resolver<'a> {
             let ident = Ident::with_empty_ctxt(name);
             let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
             if let Ok(binding) = result {
-                self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span });
+                let (def, vis) = (binding.def(), binding.vis);
+                self.macro_exports.push(Export { ident, def, vis, span });
             } else {
                 span_err!(self.session, span, E0470, "reexported macro not found");
             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 49c452cddb2..1f126fcdd81 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1107,7 +1107,11 @@ impl<'a> NameBinding<'a> {
 
     // We sometimes need to treat variants as `pub` for backwards compatibility
     fn pseudo_vis(&self) -> ty::Visibility {
-        if self.is_variant() { ty::Visibility::Public } else { self.vis }
+        if self.is_variant() && self.def().def_id().is_local() {
+            ty::Visibility::Public
+        } else {
+            self.vis
+        }
     }
 
     fn is_variant(&self) -> bool {
@@ -3602,9 +3606,9 @@ impl<'a> Resolver<'a> {
             self.populate_module_if_necessary(in_module);
 
             in_module.for_each_child_stable(|ident, _, name_binding| {
-                // abort if the module is already found
-                if let Some(_) = result {
-                    return ();
+                // abort if the module is already found or if name_binding is private external
+                if result.is_some() || !name_binding.vis.is_visible_locally() {
+                    return
                 }
                 if let Some(module) = name_binding.module() {
                     // form the path
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 3d1d7c0c48a..ad1e70a5c6e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -746,8 +746,12 @@ impl<'a> Resolver<'a> {
             }));
             if attr::contains_name(&item.attrs, "macro_export") {
                 let def = Def::Macro(def_id, MacroKind::Bang);
-                self.macro_exports
-                    .push(Export { ident: ident.modern(), def: def, span: item.span });
+                self.macro_exports.push(Export {
+                    ident: ident.modern(),
+                    def: def,
+                    vis: ty::Visibility::Public,
+                    span: item.span,
+                });
             } else {
                 self.unused_macros.insert(def_id);
             }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index d72253e5a8a..e885ec53631 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -845,8 +845,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 None => continue,
             };
 
-            if binding.vis == ty::Visibility::Public &&
-               (binding.is_import() || binding.is_macro_def()) {
+            if binding.is_import() || binding.is_macro_def() {
                 let def = binding.def();
                 if def != Def::Err {
                     if !def.def_id().is_local() {
@@ -862,7 +861,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                                 .emit();
                         }
                     }
-                    reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
+                    reexports.push(Export {
+                        ident: ident.modern(),
+                        def: def,
+                        span: binding.span,
+                        vis: binding.vis,
+                    });
                 }
             }
 
diff --git a/src/test/run-pass/hygiene/auxiliary/xcrate.rs b/src/test/run-pass/hygiene/auxiliary/xcrate.rs
new file mode 100644
index 00000000000..2ccd043097f
--- /dev/null
+++ b/src/test/run-pass/hygiene/auxiliary/xcrate.rs
@@ -0,0 +1,38 @@
+// Copyright 2017 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(decl_macro)]
+#![allow(unused)]
+
+pub use bar::test;
+
+extern crate std as foo;
+
+pub fn f() {}
+use f as f2;
+
+mod bar {
+    pub fn g() {}
+    use baz::h;
+
+    pub macro test() {
+        use std::mem;
+        use foo::cell;
+        ::f();
+        ::f2();
+        g();
+        h();
+        ::bar::h();
+    }
+}
+
+mod baz {
+    pub fn h() {}
+}
diff --git a/src/test/run-pass/hygiene/xcrate.rs b/src/test/run-pass/hygiene/xcrate.rs
new file mode 100644
index 00000000000..6df3a34d3c8
--- /dev/null
+++ b/src/test/run-pass/hygiene/xcrate.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 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.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:xcrate.rs
+
+#![feature(decl_macro)]
+
+extern crate xcrate;
+
+fn main() {
+    xcrate::test!();
+}