From 58e80400b24c09624ee602746c80d25aa18e0c86 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 29 Nov 2017 11:20:49 -0800 Subject: [PATCH] Include non-`pub` `use` and `extern crate` items in the crate metadata for macros 2.0. --- src/librustc/hir/def.rs | 4 ++ src/librustc/ich/impls_hir.rs | 1 + src/librustc/ty/mod.rs | 9 +++++ src/librustc_metadata/cstore_impl.rs | 6 +-- src/librustc_metadata/decoder.rs | 17 +++++++-- src/librustc_metadata/encoder.rs | 4 +- src/librustc_privacy/lib.rs | 13 ++++++- src/librustc_resolve/build_reduced_graph.rs | 8 ++-- src/librustc_resolve/lib.rs | 12 ++++-- src/librustc_resolve/macros.rs | 8 +++- src/librustc_resolve/resolve_imports.rs | 10 +++-- src/test/run-pass/hygiene/auxiliary/xcrate.rs | 38 +++++++++++++++++++ src/test/run-pass/hygiene/xcrate.rs | 21 ++++++++++ 13 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 src/test/run-pass/hygiene/auxiliary/xcrate.rs create mode 100644 src/test/run-pass/hygiene/xcrate.rs diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 64bcdc7920a01..a82c2f08463a6 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 77bf3da679dd7..a02efe7bd862d 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 afe999cede70d..93ef29855ce1d 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 911b4dac4e13a..bcf749da8cd44 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 eb2bcfc93c5fb..e2ad5fbf22b39 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 6cfa324797c5d..7de3b8a4264e3 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 74d92ce1c3e62..27898b5dd64bc 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 afca6ea2c0751..f19c1998d10d2 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 49c452cddb2cd..1f126fcdd8166 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 3d1d7c0c48a1e..ad1e70a5c6ec7 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 d72253e5a8a48..e885ec53631bd 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 0000000000000..2ccd043097f8e --- /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 or the MIT license +// , 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 0000000000000..6df3a34d3c87f --- /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 or the MIT license +// , 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!(); +}