@@ -1514,8 +1514,121 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
1514
1514
Item :: from_def_id_and_parts ( assoc_item. def_id , Some ( assoc_item. name ) , kind, cx)
1515
1515
}
1516
1516
1517
+ fn first_non_private_clean_path < ' tcx > (
1518
+ cx : & mut DocContext < ' tcx > ,
1519
+ path : & hir:: Path < ' tcx > ,
1520
+ new_path_segments : & ' tcx [ hir:: PathSegment < ' tcx > ] ,
1521
+ new_path_span : rustc_span:: Span ,
1522
+ ) -> Path {
1523
+ let new_hir_path =
1524
+ hir:: Path { segments : new_path_segments, res : path. res , span : new_path_span } ;
1525
+ let mut new_clean_path = clean_path ( & new_hir_path, cx) ;
1526
+ // In here we need to play with the path data one last time to provide it the
1527
+ // missing `args` and `res` of the final `Path` we get, which, since it comes
1528
+ // from a re-export, doesn't have the generics that were originally there, so
1529
+ // we add them by hand.
1530
+ if let Some ( path_last) = path. segments . last ( ) . as_ref ( )
1531
+ && let Some ( new_path_last) = new_clean_path. segments [ ..] . last_mut ( )
1532
+ && let Some ( path_last_args) = path_last. args . as_ref ( )
1533
+ && path_last. args . is_some ( )
1534
+ {
1535
+ assert ! ( new_path_last. args. is_empty( ) ) ;
1536
+ new_path_last. args = clean_generic_args ( path_last_args, cx) ;
1537
+ }
1538
+ new_clean_path
1539
+ }
1540
+
1541
+ /// The goal of this function is to return the first `Path` which is not private (ie not private
1542
+ /// or `doc(hidden)`). If it's not possible, it'll return the "end type".
1543
+ ///
1544
+ /// If the path is not a re-export or is public, it'll return `None`.
1545
+ fn first_non_private < ' tcx > (
1546
+ cx : & mut DocContext < ' tcx > ,
1547
+ hir_id : hir:: HirId ,
1548
+ path : & hir:: Path < ' tcx > ,
1549
+ ) -> Option < Path > {
1550
+ let target_def_id = path. res . opt_def_id ( ) ?;
1551
+ let ( parent_def_id, ident) = match & path. segments [ ..] {
1552
+ [ ] => return None ,
1553
+ // Relative paths are available in the same scope as the owner.
1554
+ [ leaf] => ( cx. tcx . local_parent ( hir_id. owner . def_id ) , leaf. ident ) ,
1555
+ // So are self paths.
1556
+ [ parent, leaf] if parent. ident . name == kw:: SelfLower => {
1557
+ ( cx. tcx . local_parent ( hir_id. owner . def_id ) , leaf. ident )
1558
+ }
1559
+ // Crate paths are not. We start from the crate root.
1560
+ [ parent, leaf] if matches ! ( parent. ident. name, kw:: Crate | kw:: PathRoot ) => {
1561
+ ( LOCAL_CRATE . as_def_id ( ) . as_local ( ) ?, leaf. ident )
1562
+ }
1563
+ [ parent, leaf] if parent. ident . name == kw:: Super => {
1564
+ let parent_mod = cx. tcx . parent_module ( hir_id) ;
1565
+ if let Some ( super_parent) = cx. tcx . opt_local_parent ( parent_mod) {
1566
+ ( super_parent, leaf. ident )
1567
+ } else {
1568
+ // If we can't find the parent of the parent, then the parent is already the crate.
1569
+ ( LOCAL_CRATE . as_def_id ( ) . as_local ( ) ?, leaf. ident )
1570
+ }
1571
+ }
1572
+ // Absolute paths are not. We start from the parent of the item.
1573
+ [ .., parent, leaf] => ( parent. res . opt_def_id ( ) ?. as_local ( ) ?, leaf. ident ) ,
1574
+ } ;
1575
+ let hir = cx. tcx . hir ( ) ;
1576
+ // First we try to get the `DefId` of the item.
1577
+ for child in
1578
+ cx. tcx . module_children_local ( parent_def_id) . iter ( ) . filter ( move |c| c. ident == ident)
1579
+ {
1580
+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = child. res {
1581
+ continue ;
1582
+ }
1583
+
1584
+ if let Some ( def_id) = child. res . opt_def_id ( ) && target_def_id == def_id {
1585
+ let mut last_path_res = None ;
1586
+ ' reexps: for reexp in child. reexport_chain . iter ( ) {
1587
+ if let Some ( use_def_id) = reexp. id ( ) &&
1588
+ let Some ( local_use_def_id) = use_def_id. as_local ( ) &&
1589
+ let Some ( hir:: Node :: Item ( item) ) = hir. find_by_def_id ( local_use_def_id) &&
1590
+ !item. ident . name . is_empty ( ) &&
1591
+ let hir:: ItemKind :: Use ( path, _) = item. kind
1592
+ {
1593
+ for res in & path. res {
1594
+ if let Res :: Def ( DefKind :: Ctor ( ..) , _) | Res :: SelfCtor ( ..) = res {
1595
+ continue ;
1596
+ }
1597
+ if ( cx. render_options . document_hidden ||
1598
+ !cx. tcx . is_doc_hidden ( use_def_id) ) &&
1599
+ // We never check for "cx.render_options.document_private"
1600
+ // because if a re-export is not fully public, it's never
1601
+ // documented.
1602
+ cx. tcx . local_visibility ( local_use_def_id) . is_public ( ) {
1603
+ break ' reexps;
1604
+ }
1605
+ last_path_res = Some ( ( path, res) ) ;
1606
+ continue ' reexps;
1607
+ }
1608
+ }
1609
+ }
1610
+ if !child. reexport_chain . is_empty ( ) {
1611
+ // So in here, we use the data we gathered from iterating the reexports. If
1612
+ // `last_path_res` is set, it can mean two things:
1613
+ //
1614
+ // 1. We found a public reexport.
1615
+ // 2. We didn't find a public reexport so it's the "end type" path.
1616
+ if let Some ( ( new_path, _) ) = last_path_res {
1617
+ return Some ( first_non_private_clean_path ( cx, path, new_path. segments , new_path. span ) ) ;
1618
+ }
1619
+ // If `last_path_res` is `None`, it can mean two things:
1620
+ //
1621
+ // 1. The re-export is public, no need to change anything, just use the path as is.
1622
+ // 2. Nothing was found, so let's just return the original path.
1623
+ return None ;
1624
+ }
1625
+ }
1626
+ }
1627
+ None
1628
+ }
1629
+
1517
1630
fn clean_qpath < ' tcx > ( hir_ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
1518
- let hir:: Ty { hir_id : _ , span, ref kind } = * hir_ty;
1631
+ let hir:: Ty { hir_id, span, ref kind } = * hir_ty;
1519
1632
let hir:: TyKind :: Path ( qpath) = kind else { unreachable ! ( ) } ;
1520
1633
1521
1634
match qpath {
@@ -1532,7 +1645,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
1532
1645
if let Some ( expanded) = maybe_expand_private_type_alias ( cx, path) {
1533
1646
expanded
1534
1647
} else {
1535
- let path = clean_path ( path, cx) ;
1648
+ // First we check if it's a private re-export.
1649
+ let path = if let Some ( path) = first_non_private ( cx, hir_id, & path) {
1650
+ path
1651
+ } else {
1652
+ clean_path ( path, cx)
1653
+ } ;
1536
1654
resolve_type ( cx, path)
1537
1655
}
1538
1656
}
@@ -1683,7 +1801,7 @@ fn maybe_expand_private_type_alias<'tcx>(
1683
1801
}
1684
1802
}
1685
1803
1686
- Some ( cx. enter_alias ( args, def_id. to_def_id ( ) , |cx| clean_ty ( ty, cx) ) )
1804
+ Some ( cx. enter_alias ( args, def_id. to_def_id ( ) , |cx| clean_ty ( & ty, cx) ) )
1687
1805
}
1688
1806
1689
1807
pub ( crate ) fn clean_ty < ' tcx > ( ty : & hir:: Ty < ' tcx > , cx : & mut DocContext < ' tcx > ) -> Type {
0 commit comments