@@ -1496,8 +1496,93 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14961496 Item :: from_def_id_and_parts ( assoc_item. def_id , Some ( assoc_item. name ) , kind, cx)
14971497}
14981498
1499+ /// The goal of this function is to return the first `Path` which is not private (ie not private
1500+ /// or `doc(hidden)`). If it's not possible, it'll return the "end type".
1501+ ///
1502+ /// If the path is not a re-export or is public, it'll return `None`.
1503+ fn first_not_private (
1504+ cx : & mut DocContext < ' _ > ,
1505+ hir_id : hir:: HirId ,
1506+ path : & hir:: Path < ' _ > ,
1507+ ) -> Option < Path > {
1508+ if path. segments . is_empty ( ) {
1509+ return None ;
1510+ }
1511+ let parent_def_id = if path. segments . len ( ) == 1 {
1512+ // Then it's available in the same scope as the owner.
1513+ hir_id. owner . def_id
1514+ } else {
1515+ // It's not available in the same scope, so we start from the parent of the item.
1516+ path. segments [ path. segments . len ( ) - 2 ] . res . opt_def_id ( ) ?. as_local ( ) ?
1517+ } ;
1518+ let target_def_id = path. res . opt_def_id ( ) ?;
1519+ let mut ident = path. segments . last ( ) . unwrap ( ) . ident ;
1520+ // First we try to get the `DefId` of the item.
1521+ for child in cx
1522+ . tcx
1523+ . module_children_local ( cx. tcx . local_parent ( parent_def_id) )
1524+ . iter ( )
1525+ . filter ( move |c| c. ident == ident)
1526+ {
1527+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = child. res {
1528+ continue ;
1529+ }
1530+
1531+ if let Some ( def_id) = child. res . opt_def_id ( ) && target_def_id == def_id {
1532+ let mut last_path_res = None ;
1533+ ' reexps: for reexp in child. reexport_chain . iter ( ) {
1534+ if let Some ( use_def_id) = reexp. id ( ) &&
1535+ let Some ( local_use_def_id) = use_def_id. as_local ( )
1536+ {
1537+ let hir = cx. tcx . hir ( ) ;
1538+ // let parent_mod = hir.local_def_id_to_hir_id();
1539+ for item_id in hir. module_items ( cx. tcx . local_parent ( local_use_def_id) ) {
1540+ let item = hir. item ( item_id) ;
1541+ if item. ident == ident {
1542+ match item. kind {
1543+ hir:: ItemKind :: Use ( path, _) => {
1544+ for res in & path. res {
1545+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = res {
1546+ continue ;
1547+ }
1548+ if !cx. tcx . is_doc_hidden ( use_def_id) &&
1549+ cx. tcx . local_visibility ( local_use_def_id) . is_public ( ) {
1550+ break ' reexps;
1551+ }
1552+ ident = path. segments . last ( ) . unwrap ( ) . ident ;
1553+ last_path_res = Some ( ( path, res) ) ;
1554+ continue ' reexps;
1555+ }
1556+ }
1557+ _ => { }
1558+ }
1559+ }
1560+ }
1561+ }
1562+ }
1563+ if !child. reexport_chain . is_empty ( ) {
1564+ // So in here, we use the data we gathered from iterating the reexports. If
1565+ // `last_path_res` is set, it can mean two things:
1566+ //
1567+ // 1. We found a public reexport.
1568+ // 2. We didn't find a public reexport so it's the "end type" path.
1569+ if let Some ( ( path, res) ) = last_path_res {
1570+ let path = hir:: Path { segments : path. segments , res : * res, span : path. span } ;
1571+ return Some ( clean_path ( & path, cx) ) ;
1572+ }
1573+ // If `last_path_res` is `None`, it can mean two things:
1574+ //
1575+ // 1. The re-export is public, no need to change anything, just use the path as is.
1576+ // 2. Nothing was found, so let's just return the original path.
1577+ return None ;
1578+ }
1579+ }
1580+ }
1581+ None
1582+ }
1583+
14991584fn clean_qpath < ' tcx > ( hir_ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
1500- let hir:: Ty { hir_id : _ , span, ref kind } = * hir_ty;
1585+ let hir:: Ty { hir_id, span, ref kind } = * hir_ty;
15011586 let hir:: TyKind :: Path ( qpath) = kind else { unreachable ! ( ) } ;
15021587
15031588 match qpath {
@@ -1514,7 +1599,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
15141599 if let Some ( expanded) = maybe_expand_private_type_alias ( cx, path) {
15151600 expanded
15161601 } else {
1517- let path = clean_path ( path, cx) ;
1602+ // First we check if it's a private re-export.
1603+ let path = if let Some ( path) = first_not_private ( cx, hir_id, & path) {
1604+ path
1605+ } else {
1606+ clean_path ( path, cx)
1607+ } ;
15181608 resolve_type ( cx, path)
15191609 }
15201610 }
@@ -1665,7 +1755,7 @@ fn maybe_expand_private_type_alias<'tcx>(
16651755 }
16661756 }
16671757
1668- Some ( cx. enter_alias ( args, def_id. to_def_id ( ) , |cx| clean_ty ( ty, cx) ) )
1758+ Some ( cx. enter_alias ( args, def_id. to_def_id ( ) , |cx| clean_ty ( & ty, cx) ) )
16691759}
16701760
16711761pub ( crate ) fn clean_ty < ' tcx > ( ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
0 commit comments