@@ -1467,11 +1467,14 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1467
1467
// public, even if the type alias itself is private. So, something
1468
1468
// like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
1469
1469
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 } ;
1474
1471
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
+ // ```
1475
1478
let provided_params = path. segments . last ( ) . unwrap ( ) . parameters . types ( ) . len ( ) ;
1476
1479
for ty_param in & generics. ty_params [ provided_params..] {
1477
1480
if let Some ( ref default_ty) = ty_param. default {
@@ -1500,29 +1503,32 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
1500
1503
def:: DefAssociatedTy ( ..) if self . is_quiet => {
1501
1504
// Conservatively approximate the whole type alias as public without
1502
1505
// 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.
1503
1510
return
1504
1511
}
1505
1512
def:: DefStruct ( def_id) | def:: DefTy ( def_id, _) |
1506
1513
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)
1508
1515
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
+ ) ;
1523
1529
}
1524
- self . is_public = false ;
1525
1530
}
1531
+ self . is_public = false ;
1526
1532
}
1527
1533
}
1528
1534
}
@@ -1538,24 +1544,24 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
1538
1544
// We are in quiet mode and a private type is already found, no need to proceed
1539
1545
return
1540
1546
}
1541
- // Non-local means public, local needs to be checked
1547
+ // Non-local means public (private items can't leave their crate, modulo bugs)
1542
1548
let def_id = self . tcx . trait_ref_to_def_id ( trait_ref) ;
1543
1549
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 ( ) ) ;
1556
1562
}
1557
- self . is_public = false ;
1558
1563
}
1564
+ self . is_public = false ;
1559
1565
}
1560
1566
}
1561
1567
@@ -1585,8 +1591,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1585
1591
check. is_public
1586
1592
}
1587
1593
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 {
1590
1596
let mut check = SearchInterfaceForPrivateItemsVisitor {
1591
1597
tcx : self . tcx , is_quiet : true , is_public : true , old_error_set : self . old_error_set
1592
1598
} ;
@@ -1650,7 +1656,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tc
1650
1656
// A trait impl is public when both its type and its trait are public
1651
1657
// Subitems of trait impls have inherited publicity
1652
1658
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) {
1654
1660
check. visit_generics ( generics) ;
1655
1661
for impl_item in impl_items {
1656
1662
check. visit_impl_item ( impl_item) ;
0 commit comments