@@ -1496,17 +1496,55 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
1496
1496
Item :: from_def_id_and_parts ( assoc_item. def_id , Some ( assoc_item. name ) , kind, cx)
1497
1497
}
1498
1498
1499
+ fn first_non_private_clean_path < ' tcx > (
1500
+ cx : & mut DocContext < ' tcx > ,
1501
+ path : & hir:: Path < ' tcx > ,
1502
+ mut new_path_segments : Vec < hir:: PathSegment < ' tcx > > ,
1503
+ new_path_span : rustc_span:: Span ,
1504
+ ) -> Path {
1505
+ use std:: mem:: transmute;
1506
+
1507
+ // In here we need to play with the path data one last time to provide it the
1508
+ // missing `args` and `res` of the final `Path` we get, which, since it comes
1509
+ // from a re-export, doesn't have the generics that were originally there, so
1510
+ // we add them by hand.
1511
+ if let Some ( last) = new_path_segments. last_mut ( ) {
1512
+ // `transmute` is needed because we are using a wrong lifetime. Since
1513
+ // `segments` will be dropped at the end of this block, it's fine.
1514
+ last. args = unsafe { transmute ( path. segments . last ( ) . as_ref ( ) . unwrap ( ) . args . clone ( ) ) } ;
1515
+ last. res = path. res ;
1516
+ }
1517
+ // `transmute` is needed because we are using a wrong lifetime. Since
1518
+ // `segments` will be dropped at the end of this block, it's fine.
1519
+ let path = unsafe {
1520
+ hir:: Path {
1521
+ segments : transmute ( new_path_segments. as_slice ( ) ) ,
1522
+ res : path. res ,
1523
+ span : new_path_span,
1524
+ }
1525
+ } ;
1526
+ clean_path ( & path, cx)
1527
+ }
1528
+
1499
1529
/// The goal of this function is to return the first `Path` which is not private (ie not private
1500
1530
/// or `doc(hidden)`). If it's not possible, it'll return the "end type".
1501
1531
///
1502
1532
/// If the path is not a re-export or is public, it'll return `None`.
1503
- fn first_non_private (
1504
- cx : & mut DocContext < ' _ > ,
1533
+ fn first_non_private < ' tcx > (
1534
+ cx : & mut DocContext < ' tcx > ,
1505
1535
hir_id : hir:: HirId ,
1506
- path : & hir:: Path < ' _ > ,
1536
+ path : & hir:: Path < ' tcx > ,
1507
1537
) -> Option < Path > {
1508
- use std:: mem:: transmute;
1509
-
1538
+ let use_id = path. segments . last ( ) . map ( |seg| seg. hir_id ) ?;
1539
+ let target_def_id = path. res . opt_def_id ( ) ?;
1540
+ let saved_path = cx
1541
+ . updated_qpath
1542
+ . borrow ( )
1543
+ . get ( & use_id)
1544
+ . map ( |saved_path| ( saved_path. segments . to_vec ( ) , saved_path. span ) ) ;
1545
+ if let Some ( ( segments, span) ) = saved_path {
1546
+ return Some ( first_non_private_clean_path ( cx, path, segments, span) ) ;
1547
+ }
1510
1548
let ( parent_def_id, mut ident) = match & path. segments [ ..] {
1511
1549
[ ] => return None ,
1512
1550
// Relative paths are available in the same scope as the owner.
@@ -1531,7 +1569,6 @@ fn first_non_private(
1531
1569
// Absolute paths are not. We start from the parent of the item.
1532
1570
[ .., parent, leaf] => ( parent. res . opt_def_id ( ) ?. as_local ( ) ?, leaf. ident ) ,
1533
1571
} ;
1534
- let target_def_id = path. res . opt_def_id ( ) ?;
1535
1572
// First we try to get the `DefId` of the item.
1536
1573
for child in
1537
1574
cx. tcx . module_children_local ( parent_def_id) . iter ( ) . filter ( move |c| c. ident == ident)
@@ -1577,26 +1614,9 @@ fn first_non_private(
1577
1614
// 1. We found a public reexport.
1578
1615
// 2. We didn't find a public reexport so it's the "end type" path.
1579
1616
if let Some ( ( new_path, _) ) = last_path_res {
1580
- // In here we need to play with the path data one last time to provide it the
1581
- // missing `args` and `res` of the final `Path` we get, which, since it comes
1582
- // from a re-export, doesn't have the generics that were originally there, so
1583
- // we add them by hand.
1584
- let mut segments = new_path. segments . to_vec ( ) ;
1585
- if let Some ( last) = segments. last_mut ( ) {
1586
- // `transmute` is needed because we are using a wrong lifetime. Since
1587
- // `segments` will be dropped at the end of this block, it's fine.
1588
- last. args = unsafe {
1589
- transmute (
1590
- path. segments . last ( ) . as_ref ( ) . unwrap ( ) . args . clone ( ) ,
1591
- )
1592
- } ;
1593
- last. res = path. res ;
1594
- }
1595
- // `transmute` is needed because we are using a wrong lifetime. Since
1596
- // `segments` will be dropped at the end of this block, it's fine.
1597
- let segments = unsafe { transmute ( segments. as_slice ( ) ) } ;
1598
- let new_path = hir:: Path { segments, res : path. res , span : new_path. span } ;
1599
- return Some ( clean_path ( & new_path, cx) ) ;
1617
+ cx. updated_qpath . borrow_mut ( ) . insert ( use_id, new_path. clone ( ) ) ;
1618
+ let new_path_segments = new_path. segments . to_vec ( ) ;
1619
+ return Some ( first_non_private_clean_path ( cx, path, new_path_segments, new_path. span ) ) ;
1600
1620
}
1601
1621
// If `last_path_res` is `None`, it can mean two things:
1602
1622
//
0 commit comments