@@ -1479,8 +1479,93 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14791479 Item :: from_def_id_and_parts ( assoc_item. def_id , Some ( assoc_item. name ) , kind, cx)
14801480}
14811481
1482+ /// The goal of this function is to return the first `Path` which is not private (ie not private
1483+ /// or `doc(hidden)`). If it's not possible, it'll return the "end type".
1484+ ///
1485+ /// If the path is not a re-export or is public, it'll return `None`.
1486+ fn first_not_private (
1487+ cx : & mut DocContext < ' _ > ,
1488+ hir_id : hir:: HirId ,
1489+ path : & hir:: Path < ' _ > ,
1490+ ) -> Option < Path > {
1491+ if path. segments . is_empty ( ) {
1492+ return None ;
1493+ }
1494+ let parent_def_id = if path. segments . len ( ) == 1 {
1495+ // Then it's available in the same scope as the owner.
1496+ hir_id. owner . def_id
1497+ } else {
1498+ // It's not available in the same scope, so we start from the parent of the item.
1499+ path. segments [ path. segments . len ( ) - 2 ] . res . opt_def_id ( ) ?. as_local ( ) ?
1500+ } ;
1501+ let target_def_id = path. res . opt_def_id ( ) ?;
1502+ let mut ident = path. segments . last ( ) . unwrap ( ) . ident ;
1503+ // First we try to get the `DefId` of the item.
1504+ for child in cx
1505+ . tcx
1506+ . module_children_local ( cx. tcx . local_parent ( parent_def_id) )
1507+ . iter ( )
1508+ . filter ( move |c| c. ident == ident)
1509+ {
1510+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = child. res {
1511+ continue ;
1512+ }
1513+
1514+ if let Some ( def_id) = child. res . opt_def_id ( ) && target_def_id == def_id {
1515+ let mut last_path_res = None ;
1516+ ' reexps: for reexp in child. reexport_chain . iter ( ) {
1517+ if let Some ( use_def_id) = reexp. id ( ) &&
1518+ let Some ( local_use_def_id) = use_def_id. as_local ( )
1519+ {
1520+ let hir = cx. tcx . hir ( ) ;
1521+ // let parent_mod = hir.local_def_id_to_hir_id();
1522+ for item_id in hir. module_items ( cx. tcx . local_parent ( local_use_def_id) ) {
1523+ let item = hir. item ( item_id) ;
1524+ if item. ident == ident {
1525+ match item. kind {
1526+ hir:: ItemKind :: Use ( path, _) => {
1527+ for res in & path. res {
1528+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = res {
1529+ continue ;
1530+ }
1531+ if !cx. tcx . is_doc_hidden ( use_def_id) &&
1532+ cx. tcx . local_visibility ( local_use_def_id) . is_public ( ) {
1533+ break ' reexps;
1534+ }
1535+ ident = path. segments . last ( ) . unwrap ( ) . ident ;
1536+ last_path_res = Some ( ( path, res) ) ;
1537+ continue ' reexps;
1538+ }
1539+ }
1540+ _ => { }
1541+ }
1542+ }
1543+ }
1544+ }
1545+ }
1546+ if !child. reexport_chain . is_empty ( ) {
1547+ // So in here, we use the data we gathered from iterating the reexports. If
1548+ // `last_path_res` is set, it can mean two things:
1549+ //
1550+ // 1. We found a public reexport.
1551+ // 2. We didn't find a public reexport so it's the "end type" path.
1552+ if let Some ( ( path, res) ) = last_path_res {
1553+ let path = hir:: Path { segments : path. segments , res : * res, span : path. span } ;
1554+ return Some ( clean_path ( & path, cx) ) ;
1555+ }
1556+ // If `last_path_res` is `None`, it can mean two things:
1557+ //
1558+ // 1. The re-export is public, no need to change anything, just use the path as is.
1559+ // 2. Nothing was found, so let's just return the original path.
1560+ return None ;
1561+ }
1562+ }
1563+ }
1564+ None
1565+ }
1566+
14821567fn clean_qpath < ' tcx > ( hir_ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
1483- let hir:: Ty { hir_id : _ , span, ref kind } = * hir_ty;
1568+ let hir:: Ty { hir_id, span, ref kind } = * hir_ty;
14841569 let hir:: TyKind :: Path ( qpath) = kind else { unreachable ! ( ) } ;
14851570
14861571 match qpath {
@@ -1497,7 +1582,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
14971582 if let Some ( expanded) = maybe_expand_private_type_alias ( cx, path) {
14981583 expanded
14991584 } else {
1500- let path = clean_path ( path, cx) ;
1585+ // First we check if it's a private re-export.
1586+ let path = if let Some ( path) = first_not_private ( cx, hir_id, & path) {
1587+ path
1588+ } else {
1589+ clean_path ( path, cx)
1590+ } ;
15011591 resolve_type ( cx, path)
15021592 }
15031593 }
@@ -1649,7 +1739,7 @@ fn maybe_expand_private_type_alias<'tcx>(
16491739 }
16501740 }
16511741
1652- Some ( cx. enter_alias ( substs, def_id. to_def_id ( ) , |cx| clean_ty ( ty, cx) ) )
1742+ Some ( cx. enter_alias ( substs, def_id. to_def_id ( ) , |cx| clean_ty ( & ty, cx) ) )
16531743}
16541744
16551745pub ( crate ) fn clean_ty < ' tcx > ( ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
0 commit comments