Skip to content

Commit 3358fb1

Browse files
committed
Fix the visibility of extern crate declarations and stop warning on pub extern crate
1 parent d3929b2 commit 3358fb1

File tree

9 files changed

+80
-61
lines changed

9 files changed

+80
-61
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
293293
self.external_exports.insert(def_id);
294294
let parent_link = ModuleParentLink(parent, name);
295295
let def = Def::Mod(def_id);
296-
let external_module = self.new_extern_crate_module(parent_link, def);
296+
let local_def_id = self.ast_map.local_def_id(item.id);
297+
let external_module =
298+
self.new_extern_crate_module(parent_link, def, is_public, local_def_id);
297299
self.define(parent, name, TypeNS, (external_module, sp));
298300

301+
if is_public {
302+
let export = Export { name: name, def_id: def_id };
303+
if let Some(def_id) = parent.def_id() {
304+
let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
305+
self.export_map.entry(node_id).or_insert(Vec::new()).push(export);
306+
}
307+
}
308+
299309
self.build_reduced_graph_for_external_crate(external_module);
300310
}
301311
parent

src/librustc_resolve/lib.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,10 @@ pub struct ModuleS<'a> {
806806
parent_link: ParentLink<'a>,
807807
def: Option<Def>,
808808
is_public: bool,
809-
is_extern_crate: bool,
809+
810+
// If the module is an extern crate, `def` is root of the external crate and `extern_crate_did`
811+
// is the DefId of the local `extern crate` item (otherwise, `extern_crate_did` is None).
812+
extern_crate_did: Option<DefId>,
810813

811814
resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
812815
unresolved_imports: RefCell<Vec<ImportDirective>>,
@@ -853,7 +856,7 @@ impl<'a> ModuleS<'a> {
853856
parent_link: parent_link,
854857
def: def,
855858
is_public: is_public,
856-
is_extern_crate: false,
859+
extern_crate_did: None,
857860
resolutions: RefCell::new(HashMap::new()),
858861
unresolved_imports: RefCell::new(Vec::new()),
859862
module_children: RefCell::new(NodeMap()),
@@ -917,6 +920,16 @@ impl<'a> ModuleS<'a> {
917920
self.def.as_ref().map(Def::def_id)
918921
}
919922

923+
// This returns the DefId of the crate local item that controls this module's visibility.
924+
// It is only used to compute `LastPrivate` data, and it differs from `def_id` only for extern
925+
// crates, whose `def_id` is the external crate's root, not the local `extern crate` item.
926+
fn local_def_id(&self) -> Option<DefId> {
927+
match self.extern_crate_did {
928+
Some(def_id) => Some(def_id),
929+
None => self.def_id(),
930+
}
931+
}
932+
920933
fn is_normal(&self) -> bool {
921934
match self.def {
922935
Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
@@ -1027,6 +1040,14 @@ impl<'a> NameBinding<'a> {
10271040
}
10281041
}
10291042

1043+
fn local_def_id(&self) -> Option<DefId> {
1044+
match self.kind {
1045+
NameBindingKind::Def(def) => Some(def.def_id()),
1046+
NameBindingKind::Module(ref module) => module.local_def_id(),
1047+
NameBindingKind::Import { binding, .. } => binding.local_def_id(),
1048+
}
1049+
}
1050+
10301051
fn defined_with(&self, modifiers: DefModifiers) -> bool {
10311052
self.modifiers.contains(modifiers)
10321053
}
@@ -1038,11 +1059,12 @@ impl<'a> NameBinding<'a> {
10381059
fn def_and_lp(&self) -> (Def, LastPrivate) {
10391060
let def = self.def().unwrap();
10401061
if let Def::Err = def { return (def, LastMod(AllPublic)) }
1041-
(def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))
1062+
let lp = if self.is_public() { AllPublic } else { DependsOn(self.local_def_id().unwrap()) };
1063+
(def, LastMod(lp))
10421064
}
10431065

10441066
fn is_extern_crate(&self) -> bool {
1045-
self.module().map(|module| module.is_extern_crate).unwrap_or(false)
1067+
self.module().and_then(|module| module.extern_crate_did).is_some()
10461068
}
10471069

10481070
fn is_import(&self) -> bool {
@@ -1236,9 +1258,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12361258
self.arenas.name_bindings.alloc(name_binding)
12371259
}
12381260

1239-
fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def) -> Module<'a> {
1240-
let mut module = ModuleS::new(parent_link, Some(def), false, true);
1241-
module.is_extern_crate = true;
1261+
fn new_extern_crate_module(&self,
1262+
parent_link: ParentLink<'a>,
1263+
def: Def,
1264+
is_public: bool,
1265+
local_def: DefId)
1266+
-> Module<'a> {
1267+
let mut module = ModuleS::new(parent_link, Some(def), false, is_public);
1268+
module.extern_crate_did = Some(local_def);
12421269
self.arenas.modules.alloc(module)
12431270
}
12441271

@@ -1357,7 +1384,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13571384
// Keep track of the closest private module used
13581385
// when resolving this import chain.
13591386
if !binding.is_public() {
1360-
if let Some(did) = search_module.def_id() {
1387+
if let Some(did) = search_module.local_def_id() {
13611388
closest_private = LastMod(DependsOn(did));
13621389
}
13631390
}
@@ -1462,7 +1489,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14621489
Success(PrefixFound(ref containing_module, index)) => {
14631490
search_module = containing_module;
14641491
start_index = index;
1465-
last_private = LastMod(DependsOn(containing_module.def_id()
1492+
last_private = LastMod(DependsOn(containing_module.local_def_id()
14661493
.unwrap()));
14671494
}
14681495
}
@@ -3571,7 +3598,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
35713598

35723599
if !in_module_is_extern || name_binding.is_public() {
35733600
// add the module to the lookup
3574-
let is_extern = in_module_is_extern || module.is_extern_crate;
3601+
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
35753602
worklist.push((module, path_segments, is_extern));
35763603
}
35773604
}

src/librustc_resolve/resolve_imports.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
402402
}
403403

404404
(_, &Success(name_binding)) if !name_binding.is_import() && directive.is_public => {
405-
if !name_binding.is_public() {
405+
// Disallow reexporting private items, excepting extern crates.
406+
if !name_binding.is_public() && !name_binding.is_extern_crate() {
406407
let msg = format!("`{}` is private, and cannot be reexported", source);
407408
let note_msg =
408409
format!("Consider declaring type or module `{}` with `pub`", source);
@@ -441,9 +442,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
441442
module_.decrement_outstanding_references_for(target, TypeNS);
442443

443444
let def_and_priv = |binding: &NameBinding| {
444-
let def = binding.def().unwrap();
445-
let last_private = if binding.is_public() { lp } else { DependsOn(def.def_id()) };
446-
(def, last_private)
445+
let last_private =
446+
if binding.is_public() { lp } else { DependsOn(binding.local_def_id().unwrap()) };
447+
(binding.def().unwrap(), last_private)
447448
};
448449
let value_def_and_priv = value_result.success().map(&def_and_priv);
449450
let type_def_and_priv = type_result.success().map(&def_and_priv);
@@ -493,7 +494,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
493494
build_reduced_graph::populate_module_if_necessary(self.resolver, target_module);
494495
target_module.for_each_child(|name, ns, binding| {
495496
if !binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { return }
496-
if binding.is_extern_crate() { return }
497497
self.define(module_, name, ns, directive.import(binding));
498498

499499
if ns == TypeNS && directive.is_public &&

src/libsyntax/parse/parser.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5487,13 +5487,6 @@ impl<'a> Parser<'a> {
54875487
try!(self.expect(&token::Semi));
54885488

54895489
let last_span = self.last_span;
5490-
5491-
if visibility == ast::Visibility::Public {
5492-
self.span_warn(mk_sp(lo, last_span.hi),
5493-
"`pub extern crate` does not work as expected and should not be used. \
5494-
Likely to become an error. Prefer `extern crate` and `pub use`.");
5495-
}
5496-
54975490
Ok(self.mk_item(lo,
54985491
last_span.hi,
54995492
ident,

src/test/auxiliary/privacy_reexport.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
pub extern crate core;
1112
pub use foo as bar;
1213

1314
pub mod foo {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 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+
mod foo {
12+
extern crate core;
13+
pub use self::core as reexported_core; // Check that private extern crates can be reexported
14+
}
15+
16+
// Check that private crates cannot be used from outside their modules
17+
use foo::core; //~ ERROR module `core` is inaccessible
18+
use foo::core::cell; //~ ERROR
19+
20+
fn main() {
21+
use foo::*;
22+
mod core {} // Check that private crates are not glob imported
23+
}

src/test/compile-fail/no-extern-crate-in-glob-import.rs

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/test/compile-fail/warn-pub-extern-crate.rs

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/test/run-pass/privacy-reexport.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
extern crate privacy_reexport;
1616

1717
pub fn main() {
18+
// Check that public extern crates are visible to outside crates
19+
privacy_reexport::core::cell::Cell::new(0);
20+
1821
privacy_reexport::bar::frob();
1922
}

0 commit comments

Comments
 (0)