Skip to content

Commit 187c89a

Browse files
committed
Address the comments
1 parent fcbd553 commit 187c89a

File tree

3 files changed

+47
-39
lines changed

3 files changed

+47
-39
lines changed

src/librustc_privacy/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn foo<T: Foo> (t: T) {} // ok!
4343
"##,
4444

4545
E0446: r##"
46-
A private type was used in an public type signature. Erroneous code example:
46+
A private type was used in a public type signature. Erroneous code example:
4747
4848
```
4949
mod Foo {

src/librustc_privacy/lib.rs

+43-37
Original file line numberDiff line numberDiff line change
@@ -1467,11 +1467,14 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
14671467
// public, even if the type alias itself is private. So, something
14681468
// like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
14691469
if let hir::ItemTy(ref ty, ref generics) = item.node {
1470-
let mut check = SearchInterfaceForPrivateItemsVisitor {
1471-
tcx: self.tcx, is_quiet: self.is_quiet,
1472-
is_public: true, old_error_set: self.old_error_set,
1473-
};
1470+
let mut check = SearchInterfaceForPrivateItemsVisitor { is_public: true, ..*self };
14741471
check.visit_ty(ty);
1472+
// If a private type alias with default type parameters is used in public
1473+
// interface we must ensure, that the defaults are public if they are actually used.
1474+
// ```
1475+
// type Alias<T = Private> = T;
1476+
// pub fn f() -> Alias {...} // `Private` is implicitly used here, so it must be public
1477+
// ```
14751478
let provided_params = path.segments.last().unwrap().parameters.types().len();
14761479
for ty_param in &generics.ty_params[provided_params..] {
14771480
if let Some(ref default_ty) = ty_param.default {
@@ -1500,29 +1503,32 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
15001503
def::DefAssociatedTy(..) if self.is_quiet => {
15011504
// Conservatively approximate the whole type alias as public without
15021505
// recursing into its components when determining impl publicity.
1506+
// For example, `impl <Type as Trait>::Alias {...}` may be a public impl
1507+
// even if both `Type` and `Trait` are private.
1508+
// Ideally, associated types should be substituted in the same way as
1509+
// free type aliases, but this isn't done yet.
15031510
return
15041511
}
15051512
def::DefStruct(def_id) | def::DefTy(def_id, _) |
15061513
def::DefTrait(def_id) | def::DefAssociatedTy(def_id, _) => {
1507-
// Non-local means public, local needs to be checked
1514+
// Non-local means public (private items can't leave their crate, modulo bugs)
15081515
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
1509-
if let Some(ast_map::NodeItem(ref item)) = self.tcx.map.find(node_id) {
1510-
if item.vis != hir::Public && !self.is_public_type_alias(item, path) {
1511-
if !self.is_quiet {
1512-
if self.old_error_set.contains(&ty.id) {
1513-
span_err!(self.tcx.sess, ty.span, E0446,
1514-
"private type in public interface");
1515-
} else {
1516-
self.tcx.sess.add_lint (
1517-
lint::builtin::PRIVATE_IN_PUBLIC,
1518-
node_id,
1519-
ty.span,
1520-
"private type in public interface".to_string()
1521-
);
1522-
}
1516+
let item = self.tcx.map.expect_item(node_id);
1517+
if item.vis != hir::Public && !self.is_public_type_alias(item, path) {
1518+
if !self.is_quiet {
1519+
if self.old_error_set.contains(&ty.id) {
1520+
span_err!(self.tcx.sess, ty.span, E0446,
1521+
"private type in public interface");
1522+
} else {
1523+
self.tcx.sess.add_lint (
1524+
lint::builtin::PRIVATE_IN_PUBLIC,
1525+
node_id,
1526+
ty.span,
1527+
"private type in public interface (error E0446)".to_string()
1528+
);
15231529
}
1524-
self.is_public = false;
15251530
}
1531+
self.is_public = false;
15261532
}
15271533
}
15281534
}
@@ -1538,24 +1544,24 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
15381544
// We are in quiet mode and a private type is already found, no need to proceed
15391545
return
15401546
}
1541-
// Non-local means public, local needs to be checked
1547+
// Non-local means public (private items can't leave their crate, modulo bugs)
15421548
let def_id = self.tcx.trait_ref_to_def_id(trait_ref);
15431549
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
1544-
if let Some(ast_map::NodeItem(ref item)) = self.tcx.map.find(node_id) {
1545-
if item.vis != hir::Public {
1546-
if !self.is_quiet {
1547-
if self.old_error_set.contains(&trait_ref.ref_id) {
1548-
span_err!(self.tcx.sess, trait_ref.path.span, E0445,
1549-
"private trait in public interface");
1550-
} else {
1551-
self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
1552-
node_id,
1553-
trait_ref.path.span,
1554-
"private trait in public interface".to_string());
1555-
}
1550+
let item = self.tcx.map.expect_item(node_id);
1551+
if item.vis != hir::Public {
1552+
if !self.is_quiet {
1553+
if self.old_error_set.contains(&trait_ref.ref_id) {
1554+
span_err!(self.tcx.sess, trait_ref.path.span, E0445,
1555+
"private trait in public interface");
1556+
} else {
1557+
self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
1558+
node_id,
1559+
trait_ref.path.span,
1560+
"private trait in public interface (error E0445)"
1561+
.to_string());
15561562
}
1557-
self.is_public = false;
15581563
}
1564+
self.is_public = false;
15591565
}
15601566
}
15611567

@@ -1585,8 +1591,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
15851591
check.is_public
15861592
}
15871593

1588-
// A trait is considered public if it doesn't contain any private components
1589-
fn is_public_trait(&self, trait_ref: &hir::TraitRef) -> bool {
1594+
// A trait reference is considered public if it doesn't contain any private components
1595+
fn is_public_trait_ref(&self, trait_ref: &hir::TraitRef) -> bool {
15901596
let mut check = SearchInterfaceForPrivateItemsVisitor {
15911597
tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
15921598
};
@@ -1650,7 +1656,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tc
16501656
// A trait impl is public when both its type and its trait are public
16511657
// Subitems of trait impls have inherited publicity
16521658
hir::ItemImpl(_, _, ref generics, Some(ref trait_ref), ref ty, ref impl_items) => {
1653-
if self.is_public_ty(ty) && self.is_public_trait(trait_ref) {
1659+
if self.is_public_ty(ty) && self.is_public_trait_ref(trait_ref) {
16541660
check.visit_generics(generics);
16551661
for impl_item in impl_items {
16561662
check.visit_impl_item(impl_item);

src/librustc_resolve/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,11 @@ impl fmt::Debug for Module {
905905
bitflags! {
906906
#[derive(Debug)]
907907
flags DefModifiers: u8 {
908+
// Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
909+
// or `use Enum::*` to work on private enums.
908910
const PUBLIC = 1 << 0,
909911
const IMPORTABLE = 1 << 1,
910-
// All variants are considered `PUBLIC`, but some of them live in private enums.
912+
// Variants are considered `PUBLIC`, but some of them live in private enums.
911913
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
912914
const PRIVATE_VARIANT = 1 << 2,
913915
}

0 commit comments

Comments
 (0)