Skip to content

Commit 6110084

Browse files
committed
Auto merge of #46419 - jseyfried:all_imports_in_metadata, r=nrc
Record all imports (`use`, `extern crate`) in the crate metadata This PR adds non-`pub` `use` and `extern crate` imports in the crate metadata since hygienic macros invoked in other crates may use them. We already include all other non-`pub` items in the crate metadata. This improves import suggestions in some cases. Fixes #42337. r? @nrc
2 parents dcf3db4 + 1b9d058 commit 6110084

File tree

15 files changed

+142
-28
lines changed

15 files changed

+142
-28
lines changed

src/librustc/hir/def.rs

+6
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,11 @@ 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,
133+
/// True if from a `use` or and `extern crate`.
134+
pub is_import: bool,
129135
}
130136

131137
impl CtorKind {

src/librustc/ich/impls_hir.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,9 @@ for hir::def_id::DefIndex {
10681068
impl_stable_hash_for!(struct hir::def::Export {
10691069
ident,
10701070
def,
1071-
span
1071+
vis,
1072+
span,
1073+
is_import
10721074
});
10731075

10741076
impl<'gcx> HashStable<StableHashingContext<'gcx>>

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

+19-4
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,13 @@ impl<'a, 'tcx> CrateMetadata {
639639
ext.kind()
640640
);
641641
let ident = Ident::with_empty_ctxt(name);
642-
callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
642+
callback(def::Export {
643+
ident: ident,
644+
def: def,
645+
vis: ty::Visibility::Public,
646+
span: DUMMY_SP,
647+
is_import: false,
648+
});
643649
}
644650
}
645651
return
@@ -676,7 +682,9 @@ impl<'a, 'tcx> CrateMetadata {
676682
callback(def::Export {
677683
def,
678684
ident: Ident::from_str(&self.item_name(child_index)),
685+
vis: self.get_visibility(child_index),
679686
span: self.entry(child_index).span.decode((self, sess)),
687+
is_import: false,
680688
});
681689
}
682690
}
@@ -693,23 +701,30 @@ impl<'a, 'tcx> CrateMetadata {
693701
if let (Some(def), Some(name)) =
694702
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
695703
let ident = Ident::from_str(&name);
696-
callback(def::Export { def: def, ident: ident, span: span });
704+
let vis = self.get_visibility(child_index);
705+
let is_import = false;
706+
callback(def::Export { def, ident, vis, span, is_import });
697707
// For non-reexport structs and variants add their constructors to children.
698708
// Reexport lists automatically contain constructors when necessary.
699709
match def {
700710
Def::Struct(..) => {
701711
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
702712
let ctor_kind = self.get_ctor_kind(child_index);
703713
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
704-
callback(def::Export { def: ctor_def, ident: ident, span: span });
714+
callback(def::Export {
715+
def: ctor_def,
716+
vis: self.get_visibility(ctor_def_id.index),
717+
ident, span, is_import,
718+
});
705719
}
706720
}
707721
Def::Variant(def_id) => {
708722
// Braced variants, unlike structs, generate unusable names in
709723
// value namespace, they are reserved for possible future use.
710724
let ctor_kind = self.get_ctor_kind(child_index);
711725
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
712-
callback(def::Export { def: ctor_def, ident: ident, span: span });
726+
let vis = self.get_visibility(child_index);
727+
callback(def::Export { def: ctor_def, ident, vis, span, is_import });
713728
}
714729
_ => {}
715730
}

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, is_import: true });
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
@@ -1108,7 +1108,11 @@ impl<'a> NameBinding<'a> {
11081108

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

11141118
fn is_variant(&self) -> bool {
@@ -3613,9 +3617,9 @@ impl<'a> Resolver<'a> {
36133617
self.populate_module_if_necessary(in_module);
36143618

36153619
in_module.for_each_child_stable(|ident, _, name_binding| {
3616-
// abort if the module is already found
3617-
if let Some(_) = result {
3618-
return ();
3620+
// abort if the module is already found or if name_binding is private external
3621+
if result.is_some() || !name_binding.vis.is_visible_locally() {
3622+
return
36193623
}
36203624
if let Some(module) = name_binding.module() {
36213625
// form the path

src/librustc_resolve/macros.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,13 @@ 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+
is_import: false,
755+
});
751756
} else {
752757
self.unused_macros.insert(def_id);
753758
}

src/librustc_resolve/resolve_imports.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -898,8 +898,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
898898
None => continue,
899899
};
900900

901-
if binding.vis == ty::Visibility::Public &&
902-
(binding.is_import() || binding.is_macro_def()) {
901+
if binding.is_import() || binding.is_macro_def() {
903902
let def = binding.def();
904903
if def != Def::Err {
905904
if !def.def_id().is_local() {
@@ -915,7 +914,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
915914
.emit();
916915
}
917916
}
918-
reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
917+
reexports.push(Export {
918+
ident: ident.modern(),
919+
def: def,
920+
span: binding.span,
921+
vis: binding.vis,
922+
is_import: true,
923+
});
919924
}
920925
}
921926

src/librustdoc/clean/inline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
392392
let mut visited = FxHashSet();
393393
for &item in cx.tcx.item_children(did).iter() {
394394
let def_id = item.def.def_id();
395-
if cx.tcx.visibility(def_id) == ty::Visibility::Public {
395+
if item.vis == ty::Visibility::Public {
396396
if !visited.insert(def_id) { continue }
397397
if let Some(i) = try_inline(cx, item.def, item.ident.name) {
398398
items.extend(i)

src/librustdoc/visit_lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
6868
}
6969

7070
for item in self.cx.tcx.item_children(def_id).iter() {
71-
self.visit_item(item.def);
71+
if !item.is_import || item.vis == Visibility::Public {
72+
self.visit_item(item.def);
73+
}
7274
}
7375
}
7476

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)