Skip to content

Commit 58e8040

Browse files
committed
Include non-pub use and extern crate items in the crate metadata for macros 2.0.
1 parent 8503b3f commit 58e8040

File tree

13 files changed

+126
-25
lines changed

13 files changed

+126
-25
lines changed

src/librustc/hir/def.rs

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use syntax::ast;
1414
use syntax::ext::base::MacroKind;
1515
use syntax_pos::Span;
1616
use hir;
17+
use ty;
1718

1819
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
1920
pub enum CtorKind {
@@ -126,6 +127,9 @@ pub struct Export {
126127
pub def: Def,
127128
/// The span of the target definition.
128129
pub span: Span,
130+
/// The visibility of the export.
131+
/// We include non-`pub` exports for hygienic macros that get used from extern crates.
132+
pub vis: ty::Visibility,
129133
}
130134

131135
impl CtorKind {

src/librustc/ich/impls_hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,7 @@ for hir::def_id::DefIndex {
11621162
impl_stable_hash_for!(struct hir::def::Export {
11631163
ident,
11641164
def,
1165+
vis,
11651166
span
11661167
});
11671168

src/librustc/ty/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,15 @@ impl Visibility {
307307

308308
self.is_accessible_from(vis_restriction, tree)
309309
}
310+
311+
// Returns true if this item is visible anywhere in the local crate.
312+
pub fn is_visible_locally(self) -> bool {
313+
match self {
314+
Visibility::Public => true,
315+
Visibility::Restricted(def_id) => def_id.is_local(),
316+
Visibility::Invisible => false,
317+
}
318+
}
310319
}
311320

312321
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]

src/librustc_metadata/cstore_impl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,12 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
305305
let mut add_child = |bfs_queue: &mut VecDeque<_>,
306306
child: &def::Export,
307307
parent: DefId| {
308-
let child = child.def.def_id();
309-
310-
if tcx.visibility(child) != ty::Visibility::Public {
308+
if child.vis != ty::Visibility::Public {
311309
return;
312310
}
313311

312+
let child = child.def.def_id();
313+
314314
match visible_parent_map.entry(child) {
315315
Entry::Occupied(mut entry) => {
316316
// If `child` is defined in crate `cnum`, ensure

src/librustc_metadata/decoder.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,12 @@ impl<'a, 'tcx> CrateMetadata {
631631
ext.kind()
632632
);
633633
let ident = Ident::with_empty_ctxt(name);
634-
callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
634+
callback(def::Export {
635+
ident: ident,
636+
def: def,
637+
vis: ty::Visibility::Public,
638+
span: DUMMY_SP,
639+
});
635640
}
636641
}
637642
return
@@ -668,6 +673,7 @@ impl<'a, 'tcx> CrateMetadata {
668673
callback(def::Export {
669674
def,
670675
ident: Ident::from_str(&self.item_name(child_index)),
676+
vis: self.get_visibility(child_index),
671677
span: self.entry(child_index).span.decode((self, sess)),
672678
});
673679
}
@@ -685,23 +691,26 @@ impl<'a, 'tcx> CrateMetadata {
685691
if let (Some(def), Some(name)) =
686692
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
687693
let ident = Ident::from_str(&name);
688-
callback(def::Export { def: def, ident: ident, span: span });
694+
let vis = self.get_visibility(child_index);
695+
callback(def::Export { def, ident, vis, span });
689696
// For non-reexport structs and variants add their constructors to children.
690697
// Reexport lists automatically contain constructors when necessary.
691698
match def {
692699
Def::Struct(..) => {
693700
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
694701
let ctor_kind = self.get_ctor_kind(child_index);
695702
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
696-
callback(def::Export { def: ctor_def, ident: ident, span: span });
703+
let vis = self.get_visibility(ctor_def_id.index);
704+
callback(def::Export { def: ctor_def, ident, vis, span });
697705
}
698706
}
699707
Def::Variant(def_id) => {
700708
// Braced variants, unlike structs, generate unusable names in
701709
// value namespace, they are reserved for possible future use.
702710
let ctor_kind = self.get_ctor_kind(child_index);
703711
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
704-
callback(def::Export { def: ctor_def, ident: ident, span: span });
712+
let vis = self.get_visibility(child_index);
713+
callback(def::Export { def: ctor_def, ident, vis, span });
705714
}
706715
_ => {}
707716
}

src/librustc_metadata/encoder.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
506506

507507
let data = ModData {
508508
reexports: match tcx.module_exports(def_id) {
509-
Some(ref exports) if *vis == hir::Public => {
510-
self.lazy_seq_from_slice(exports.as_slice())
511-
}
509+
Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
512510
_ => LazySeq::empty(),
513511
},
514512
};

src/librustc_privacy/lib.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,9 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
331331
if let Some(exports) = self.tcx.module_exports(def_id) {
332332
for export in exports.iter() {
333333
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
334-
self.update(node_id, Some(AccessLevel::Exported));
334+
if export.vis == ty::Visibility::Public {
335+
self.update(node_id, Some(AccessLevel::Exported));
336+
}
335337
}
336338
}
337339
}
@@ -365,6 +367,15 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
365367
for id in &module.item_ids {
366368
self.update(id.id, level);
367369
}
370+
let def_id = self.tcx.hir.local_def_id(module_id);
371+
if let Some(exports) = self.tcx.module_exports(def_id) {
372+
for export in exports.iter() {
373+
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
374+
self.update(node_id, level);
375+
}
376+
}
377+
}
378+
368379
if module_id == ast::CRATE_NODE_ID {
369380
break
370381
}

src/librustc_resolve/build_reduced_graph.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -466,11 +466,8 @@ impl<'a> Resolver<'a> {
466466

467467
/// Builds the reduced graph for a single item in an external crate.
468468
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
469-
let ident = child.ident;
470-
let def = child.def;
469+
let Export { ident, def, vis, span } = child;
471470
let def_id = def.def_id();
472-
let vis = self.cstore.visibility_untracked(def_id);
473-
let span = child.span;
474471
let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
475472
match def {
476473
Def::Mod(..) | Def::Enum(..) => {
@@ -674,7 +671,8 @@ impl<'a> Resolver<'a> {
674671
let ident = Ident::with_empty_ctxt(name);
675672
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
676673
if let Ok(binding) = result {
677-
self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span });
674+
let (def, vis) = (binding.def(), binding.vis);
675+
self.macro_exports.push(Export { ident, def, vis, span });
678676
} else {
679677
span_err!(self.session, span, E0470, "reexported macro not found");
680678
}

src/librustc_resolve/lib.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,11 @@ impl<'a> NameBinding<'a> {
11071107

11081108
// We sometimes need to treat variants as `pub` for backwards compatibility
11091109
fn pseudo_vis(&self) -> ty::Visibility {
1110-
if self.is_variant() { ty::Visibility::Public } else { self.vis }
1110+
if self.is_variant() && self.def().def_id().is_local() {
1111+
ty::Visibility::Public
1112+
} else {
1113+
self.vis
1114+
}
11111115
}
11121116

11131117
fn is_variant(&self) -> bool {
@@ -3602,9 +3606,9 @@ impl<'a> Resolver<'a> {
36023606
self.populate_module_if_necessary(in_module);
36033607

36043608
in_module.for_each_child_stable(|ident, _, name_binding| {
3605-
// abort if the module is already found
3606-
if let Some(_) = result {
3607-
return ();
3609+
// abort if the module is already found or if name_binding is private external
3610+
if result.is_some() || !name_binding.vis.is_visible_locally() {
3611+
return
36083612
}
36093613
if let Some(module) = name_binding.module() {
36103614
// form the path

src/librustc_resolve/macros.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,12 @@ impl<'a> Resolver<'a> {
746746
}));
747747
if attr::contains_name(&item.attrs, "macro_export") {
748748
let def = Def::Macro(def_id, MacroKind::Bang);
749-
self.macro_exports
750-
.push(Export { ident: ident.modern(), def: def, span: item.span });
749+
self.macro_exports.push(Export {
750+
ident: ident.modern(),
751+
def: def,
752+
vis: ty::Visibility::Public,
753+
span: item.span,
754+
});
751755
} else {
752756
self.unused_macros.insert(def_id);
753757
}

src/librustc_resolve/resolve_imports.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
845845
None => continue,
846846
};
847847

848-
if binding.vis == ty::Visibility::Public &&
849-
(binding.is_import() || binding.is_macro_def()) {
848+
if binding.is_import() || binding.is_macro_def() {
850849
let def = binding.def();
851850
if def != Def::Err {
852851
if !def.def_id().is_local() {
@@ -862,7 +861,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
862861
.emit();
863862
}
864863
}
865-
reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
864+
reexports.push(Export {
865+
ident: ident.modern(),
866+
def: def,
867+
span: binding.span,
868+
vis: binding.vis,
869+
});
866870
}
867871
}
868872

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(decl_macro)]
12+
#![allow(unused)]
13+
14+
pub use bar::test;
15+
16+
extern crate std as foo;
17+
18+
pub fn f() {}
19+
use f as f2;
20+
21+
mod bar {
22+
pub fn g() {}
23+
use baz::h;
24+
25+
pub macro test() {
26+
use std::mem;
27+
use foo::cell;
28+
::f();
29+
::f2();
30+
g();
31+
h();
32+
::bar::h();
33+
}
34+
}
35+
36+
mod baz {
37+
pub fn h() {}
38+
}

src/test/run-pass/hygiene/xcrate.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-pretty pretty-printing is unhygienic
12+
13+
// aux-build:xcrate.rs
14+
15+
#![feature(decl_macro)]
16+
17+
extern crate xcrate;
18+
19+
fn main() {
20+
xcrate::test!();
21+
}

0 commit comments

Comments
 (0)