Include non-pub
use
and extern crate
items in the crate metadata for macros 2.0.
This commit is contained in:
parent
8503b3ff82
commit
58e80400b2
13 changed files with 126 additions and 25 deletions
|
@ -14,6 +14,7 @@ use syntax::ast;
|
||||||
use syntax::ext::base::MacroKind;
|
use syntax::ext::base::MacroKind;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use hir;
|
use hir;
|
||||||
|
use ty;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum CtorKind {
|
pub enum CtorKind {
|
||||||
|
@ -126,6 +127,9 @@ pub struct Export {
|
||||||
pub def: Def,
|
pub def: Def,
|
||||||
/// The span of the target definition.
|
/// The span of the target definition.
|
||||||
pub span: Span,
|
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 {
|
impl CtorKind {
|
||||||
|
|
|
@ -1162,6 +1162,7 @@ for hir::def_id::DefIndex {
|
||||||
impl_stable_hash_for!(struct hir::def::Export {
|
impl_stable_hash_for!(struct hir::def::Export {
|
||||||
ident,
|
ident,
|
||||||
def,
|
def,
|
||||||
|
vis,
|
||||||
span
|
span
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,15 @@ impl Visibility {
|
||||||
|
|
||||||
self.is_accessible_from(vis_restriction, tree)
|
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)]
|
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
|
||||||
|
|
|
@ -305,12 +305,12 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
||||||
let mut add_child = |bfs_queue: &mut VecDeque<_>,
|
let mut add_child = |bfs_queue: &mut VecDeque<_>,
|
||||||
child: &def::Export,
|
child: &def::Export,
|
||||||
parent: DefId| {
|
parent: DefId| {
|
||||||
let child = child.def.def_id();
|
if child.vis != ty::Visibility::Public {
|
||||||
|
|
||||||
if tcx.visibility(child) != ty::Visibility::Public {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let child = child.def.def_id();
|
||||||
|
|
||||||
match visible_parent_map.entry(child) {
|
match visible_parent_map.entry(child) {
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
// If `child` is defined in crate `cnum`, ensure
|
// If `child` is defined in crate `cnum`, ensure
|
||||||
|
|
|
@ -631,7 +631,12 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
ext.kind()
|
ext.kind()
|
||||||
);
|
);
|
||||||
let ident = Ident::with_empty_ctxt(name);
|
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
|
return
|
||||||
|
@ -668,6 +673,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
callback(def::Export {
|
callback(def::Export {
|
||||||
def,
|
def,
|
||||||
ident: Ident::from_str(&self.item_name(child_index)),
|
ident: Ident::from_str(&self.item_name(child_index)),
|
||||||
|
vis: self.get_visibility(child_index),
|
||||||
span: self.entry(child_index).span.decode((self, sess)),
|
span: self.entry(child_index).span.decode((self, sess)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -685,7 +691,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
if let (Some(def), Some(name)) =
|
if let (Some(def), Some(name)) =
|
||||||
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
|
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
|
||||||
let ident = Ident::from_str(&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.
|
// For non-reexport structs and variants add their constructors to children.
|
||||||
// Reexport lists automatically contain constructors when necessary.
|
// Reexport lists automatically contain constructors when necessary.
|
||||||
match def {
|
match def {
|
||||||
|
@ -693,7 +700,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
|
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_kind = self.get_ctor_kind(child_index);
|
||||||
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
|
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) => {
|
Def::Variant(def_id) => {
|
||||||
|
@ -701,7 +709,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
// value namespace, they are reserved for possible future use.
|
// value namespace, they are reserved for possible future use.
|
||||||
let ctor_kind = self.get_ctor_kind(child_index);
|
let ctor_kind = self.get_ctor_kind(child_index);
|
||||||
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
|
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 });
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,9 +506,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
let data = ModData {
|
let data = ModData {
|
||||||
reexports: match tcx.module_exports(def_id) {
|
reexports: match tcx.module_exports(def_id) {
|
||||||
Some(ref exports) if *vis == hir::Public => {
|
Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
|
||||||
self.lazy_seq_from_slice(exports.as_slice())
|
|
||||||
}
|
|
||||||
_ => LazySeq::empty(),
|
_ => LazySeq::empty(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -331,7 +331,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
|
||||||
if let Some(exports) = self.tcx.module_exports(def_id) {
|
if let Some(exports) = self.tcx.module_exports(def_id) {
|
||||||
for export in exports.iter() {
|
for export in exports.iter() {
|
||||||
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
|
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 {
|
for id in &module.item_ids {
|
||||||
self.update(id.id, level);
|
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 {
|
if module_id == ast::CRATE_NODE_ID {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,11 +466,8 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
/// Builds the reduced graph for a single item in an external crate.
|
/// 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) {
|
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
|
||||||
let ident = child.ident;
|
let Export { ident, def, vis, span } = child;
|
||||||
let def = child.def;
|
|
||||||
let def_id = def.def_id();
|
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
|
let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
|
||||||
match def {
|
match def {
|
||||||
Def::Mod(..) | Def::Enum(..) => {
|
Def::Mod(..) | Def::Enum(..) => {
|
||||||
|
@ -674,7 +671,8 @@ impl<'a> Resolver<'a> {
|
||||||
let ident = Ident::with_empty_ctxt(name);
|
let ident = Ident::with_empty_ctxt(name);
|
||||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
|
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
|
||||||
if let Ok(binding) = result {
|
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 {
|
} else {
|
||||||
span_err!(self.session, span, E0470, "reexported macro not found");
|
span_err!(self.session, span, E0470, "reexported macro not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1107,7 +1107,11 @@ impl<'a> NameBinding<'a> {
|
||||||
|
|
||||||
// We sometimes need to treat variants as `pub` for backwards compatibility
|
// We sometimes need to treat variants as `pub` for backwards compatibility
|
||||||
fn pseudo_vis(&self) -> ty::Visibility {
|
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 {
|
fn is_variant(&self) -> bool {
|
||||||
|
@ -3602,9 +3606,9 @@ impl<'a> Resolver<'a> {
|
||||||
self.populate_module_if_necessary(in_module);
|
self.populate_module_if_necessary(in_module);
|
||||||
|
|
||||||
in_module.for_each_child_stable(|ident, _, name_binding| {
|
in_module.for_each_child_stable(|ident, _, name_binding| {
|
||||||
// abort if the module is already found
|
// abort if the module is already found or if name_binding is private external
|
||||||
if let Some(_) = result {
|
if result.is_some() || !name_binding.vis.is_visible_locally() {
|
||||||
return ();
|
return
|
||||||
}
|
}
|
||||||
if let Some(module) = name_binding.module() {
|
if let Some(module) = name_binding.module() {
|
||||||
// form the path
|
// form the path
|
||||||
|
|
|
@ -746,8 +746,12 @@ impl<'a> Resolver<'a> {
|
||||||
}));
|
}));
|
||||||
if attr::contains_name(&item.attrs, "macro_export") {
|
if attr::contains_name(&item.attrs, "macro_export") {
|
||||||
let def = Def::Macro(def_id, MacroKind::Bang);
|
let def = Def::Macro(def_id, MacroKind::Bang);
|
||||||
self.macro_exports
|
self.macro_exports.push(Export {
|
||||||
.push(Export { ident: ident.modern(), def: def, span: item.span });
|
ident: ident.modern(),
|
||||||
|
def: def,
|
||||||
|
vis: ty::Visibility::Public,
|
||||||
|
span: item.span,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
self.unused_macros.insert(def_id);
|
self.unused_macros.insert(def_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -845,8 +845,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
if binding.vis == ty::Visibility::Public &&
|
if binding.is_import() || binding.is_macro_def() {
|
||||||
(binding.is_import() || binding.is_macro_def()) {
|
|
||||||
let def = binding.def();
|
let def = binding.def();
|
||||||
if def != Def::Err {
|
if def != Def::Err {
|
||||||
if !def.def_id().is_local() {
|
if !def.def_id().is_local() {
|
||||||
|
@ -862,7 +861,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||||
.emit();
|
.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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
src/test/run-pass/hygiene/auxiliary/xcrate.rs
Normal file
38
src/test/run-pass/hygiene/auxiliary/xcrate.rs
Normal file
|
@ -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() {}
|
||||||
|
}
|
21
src/test/run-pass/hygiene/xcrate.rs
Normal file
21
src/test/run-pass/hygiene/xcrate.rs
Normal file
|
@ -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!();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue