Skip to content

Commit 7330747

Browse files
committed
Prohibit private variant reexports
1 parent a09246a commit 7330747

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
390390
let module = Module::new(parent_link, Some(def), false, is_public);
391391
name_bindings.define_module(module.clone(), sp);
392392

393+
let variant_modifiers = if is_public {
394+
DefModifiers::empty()
395+
} else {
396+
DefModifiers::PRIVATE_VARIANT
397+
};
393398
for variant in &(*enum_definition).variants {
394399
let item_def_id = self.ast_map.local_def_id(item.id);
395-
self.build_reduced_graph_for_variant(variant, item_def_id, &module);
400+
self.build_reduced_graph_for_variant(variant, item_def_id,
401+
&module, variant_modifiers);
396402
}
397403
parent.clone()
398404
}
@@ -494,7 +500,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
494500
fn build_reduced_graph_for_variant(&mut self,
495501
variant: &Variant,
496502
item_id: DefId,
497-
parent: &Rc<Module>) {
503+
parent: &Rc<Module>,
504+
variant_modifiers: DefModifiers) {
498505
let name = variant.node.name;
499506
let is_exported = if variant.node.data.is_struct() {
500507
// Not adding fields for variants as they are not accessed with a self receiver
@@ -512,12 +519,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
512519
self.ast_map.local_def_id(variant.node.data.id()),
513520
is_exported),
514521
variant.span,
515-
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
522+
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
516523
child.define_type(DefVariant(item_id,
517524
self.ast_map.local_def_id(variant.node.data.id()),
518525
is_exported),
519526
variant.span,
520-
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
527+
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
521528
}
522529

523530
/// Constructs the reduced graph for one foreign item.

src/librustc_resolve/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,9 @@ bitflags! {
907907
flags DefModifiers: u8 {
908908
const PUBLIC = 1 << 0,
909909
const IMPORTABLE = 1 << 1,
910+
// All variants are considered `PUBLIC`, but some of them live in private enums.
911+
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
912+
const PRIVATE_VARIANT = 1 << 2,
910913
}
911914
}
912915

@@ -1007,6 +1010,11 @@ impl NameBinding {
10071010
self.defined_with(DefModifiers::PUBLIC)
10081011
}
10091012

1013+
fn is_reexportable(&self) -> bool {
1014+
self.defined_with(DefModifiers::PUBLIC) &&
1015+
!self.defined_with(DefModifiers::PRIVATE_VARIANT)
1016+
}
1017+
10101018
fn def_and_lp(&self) -> (Def, LastPrivate) {
10111019
let def = self.def().unwrap();
10121020
(def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))

src/librustc_resolve/resolve_imports.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
443443
debug!("(resolving single import) found value binding");
444444
value_result = BoundResult(target_module.clone(),
445445
child_name_bindings.value_ns.clone());
446-
if directive.is_public && !child_name_bindings.value_ns.is_public() {
446+
if directive.is_public && !child_name_bindings.value_ns.is_reexportable() {
447447
let msg = format!("`{}` is private, and cannot be reexported", source);
448448
let note_msg = format!("Consider marking `{}` as `pub` in the imported \
449449
module",
@@ -458,7 +458,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
458458
type_result = BoundResult(target_module.clone(),
459459
child_name_bindings.type_ns.clone());
460460
if !pub_err && directive.is_public &&
461-
!child_name_bindings.type_ns.is_public() {
461+
!child_name_bindings.type_ns.is_reexportable() {
462462
let msg = format!("`{}` is private, and cannot be reexported", source);
463463
let note_msg = format!("Consider declaring module `{}` as a `pub mod`",
464464
source);

src/test/compile-fail/issue-17546.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use foo::NoResult; // Through a re-export
1414
mod foo {
1515
pub use self::MyEnum::NoResult;
1616

17-
enum MyEnum {
17+
pub enum MyEnum {
1818
Result,
1919
NoResult
2020
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 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+
pub use E::V; //~ERROR `V` is private, and cannot be reexported
12+
13+
enum E { V }
14+
15+
fn main() {}

0 commit comments

Comments
 (0)