@@ -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) ;
0 commit comments