|  | 
| 7 | 7 | //! some of them support an alternate format that emits text, but that should | 
| 8 | 8 | //! not be used external to this module. | 
| 9 | 9 | 
 | 
| 10 |  | -use std::borrow::Cow; | 
| 11 | 10 | use std::cmp::Ordering; | 
| 12 | 11 | use std::fmt::{self, Display, Write}; | 
| 13 | 12 | use std::iter::{self, once}; | 
| @@ -37,115 +36,6 @@ use crate::html::render::Context; | 
| 37 | 36 | use crate::joined::Joined as _; | 
| 38 | 37 | use crate::passes::collect_intra_doc_links::UrlFragment; | 
| 39 | 38 | 
 | 
| 40 |  | -pub(crate) trait Print { | 
| 41 |  | -    fn print(self, buffer: &mut Buffer); | 
| 42 |  | -} | 
| 43 |  | - | 
| 44 |  | -impl<F> Print for F | 
| 45 |  | -where | 
| 46 |  | -    F: FnOnce(&mut Buffer), | 
| 47 |  | -{ | 
| 48 |  | -    fn print(self, buffer: &mut Buffer) { | 
| 49 |  | -        (self)(buffer) | 
| 50 |  | -    } | 
| 51 |  | -} | 
| 52 |  | - | 
| 53 |  | -impl Print for String { | 
| 54 |  | -    fn print(self, buffer: &mut Buffer) { | 
| 55 |  | -        buffer.write_str(&self); | 
| 56 |  | -    } | 
| 57 |  | -} | 
| 58 |  | - | 
| 59 |  | -impl Print for &'_ str { | 
| 60 |  | -    fn print(self, buffer: &mut Buffer) { | 
| 61 |  | -        buffer.write_str(self); | 
| 62 |  | -    } | 
| 63 |  | -} | 
| 64 |  | - | 
| 65 |  | -#[derive(Debug, Clone)] | 
| 66 |  | -pub(crate) struct Buffer { | 
| 67 |  | -    for_html: bool, | 
| 68 |  | -    buffer: String, | 
| 69 |  | -} | 
| 70 |  | - | 
| 71 |  | -impl core::fmt::Write for Buffer { | 
| 72 |  | -    #[inline] | 
| 73 |  | -    fn write_str(&mut self, s: &str) -> fmt::Result { | 
| 74 |  | -        self.buffer.write_str(s) | 
| 75 |  | -    } | 
| 76 |  | - | 
| 77 |  | -    #[inline] | 
| 78 |  | -    fn write_char(&mut self, c: char) -> fmt::Result { | 
| 79 |  | -        self.buffer.write_char(c) | 
| 80 |  | -    } | 
| 81 |  | - | 
| 82 |  | -    #[inline] | 
| 83 |  | -    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { | 
| 84 |  | -        self.buffer.write_fmt(args) | 
| 85 |  | -    } | 
| 86 |  | -} | 
| 87 |  | - | 
| 88 |  | -impl Buffer { | 
| 89 |  | -    pub(crate) fn empty_from(v: &Buffer) -> Buffer { | 
| 90 |  | -        Buffer { for_html: v.for_html, buffer: String::new() } | 
| 91 |  | -    } | 
| 92 |  | - | 
| 93 |  | -    pub(crate) fn html() -> Buffer { | 
| 94 |  | -        Buffer { for_html: true, buffer: String::new() } | 
| 95 |  | -    } | 
| 96 |  | - | 
| 97 |  | -    pub(crate) fn new() -> Buffer { | 
| 98 |  | -        Buffer { for_html: false, buffer: String::new() } | 
| 99 |  | -    } | 
| 100 |  | - | 
| 101 |  | -    pub(crate) fn is_empty(&self) -> bool { | 
| 102 |  | -        self.buffer.is_empty() | 
| 103 |  | -    } | 
| 104 |  | - | 
| 105 |  | -    pub(crate) fn into_inner(self) -> String { | 
| 106 |  | -        self.buffer | 
| 107 |  | -    } | 
| 108 |  | - | 
| 109 |  | -    pub(crate) fn push(&mut self, c: char) { | 
| 110 |  | -        self.buffer.push(c); | 
| 111 |  | -    } | 
| 112 |  | - | 
| 113 |  | -    pub(crate) fn push_str(&mut self, s: &str) { | 
| 114 |  | -        self.buffer.push_str(s); | 
| 115 |  | -    } | 
| 116 |  | - | 
| 117 |  | -    pub(crate) fn push_buffer(&mut self, other: Buffer) { | 
| 118 |  | -        self.buffer.push_str(&other.buffer); | 
| 119 |  | -    } | 
| 120 |  | - | 
| 121 |  | -    // Intended for consumption by write! and writeln! (std::fmt) but without | 
| 122 |  | -    // the fmt::Result return type imposed by fmt::Write (and avoiding the trait | 
| 123 |  | -    // import). | 
| 124 |  | -    pub(crate) fn write_str(&mut self, s: &str) { | 
| 125 |  | -        self.buffer.push_str(s); | 
| 126 |  | -    } | 
| 127 |  | - | 
| 128 |  | -    // Intended for consumption by write! and writeln! (std::fmt) but without | 
| 129 |  | -    // the fmt::Result return type imposed by fmt::Write (and avoiding the trait | 
| 130 |  | -    // import). | 
| 131 |  | -    pub(crate) fn write_fmt(&mut self, v: fmt::Arguments<'_>) { | 
| 132 |  | -        self.buffer.write_fmt(v).unwrap(); | 
| 133 |  | -    } | 
| 134 |  | - | 
| 135 |  | -    pub(crate) fn to_display<T: Print>(mut self, t: T) -> String { | 
| 136 |  | -        t.print(&mut self); | 
| 137 |  | -        self.into_inner() | 
| 138 |  | -    } | 
| 139 |  | - | 
| 140 |  | -    pub(crate) fn reserve(&mut self, additional: usize) { | 
| 141 |  | -        self.buffer.reserve(additional) | 
| 142 |  | -    } | 
| 143 |  | - | 
| 144 |  | -    pub(crate) fn len(&self) -> usize { | 
| 145 |  | -        self.buffer.len() | 
| 146 |  | -    } | 
| 147 |  | -} | 
| 148 |  | - | 
| 149 | 39 | pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>( | 
| 150 | 40 |     bounds: &'a [clean::GenericBound], | 
| 151 | 41 |     cx: &'a Context<'tcx>, | 
| @@ -772,27 +662,29 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont | 
| 772 | 662 |     else { | 
| 773 | 663 |         return String::new(); | 
| 774 | 664 |     }; | 
| 775 |  | -    let mut buf = Buffer::new(); | 
| 776 | 665 |     let fqp = if *shortty == ItemType::Primitive { | 
| 777 | 666 |         // primitives are documented in a crate, but not actually part of it | 
| 778 | 667 |         &fqp[fqp.len() - 1..] | 
| 779 | 668 |     } else { | 
| 780 | 669 |         fqp | 
| 781 | 670 |     }; | 
| 782 |  | -    if let &Some(UrlFragment::Item(id)) = fragment { | 
| 783 |  | -        write!(buf, "{} ", cx.tcx().def_descr(id)); | 
| 784 |  | -        for component in fqp { | 
| 785 |  | -            write!(buf, "{component}::"); | 
| 786 |  | -        } | 
| 787 |  | -        write!(buf, "{}", cx.tcx().item_name(id)); | 
| 788 |  | -    } else if !fqp.is_empty() { | 
| 789 |  | -        let mut fqp_it = fqp.iter(); | 
| 790 |  | -        write!(buf, "{shortty} {}", fqp_it.next().unwrap()); | 
| 791 |  | -        for component in fqp_it { | 
| 792 |  | -            write!(buf, "::{component}"); | 
|  | 671 | +    fmt::from_fn(|f| { | 
|  | 672 | +        if let &Some(UrlFragment::Item(id)) = fragment { | 
|  | 673 | +            write!(f, "{} ", cx.tcx().def_descr(id))?; | 
|  | 674 | +            for component in fqp { | 
|  | 675 | +                write!(f, "{component}::")?; | 
|  | 676 | +            } | 
|  | 677 | +            write!(f, "{}", cx.tcx().item_name(id))?; | 
|  | 678 | +        } else if !fqp.is_empty() { | 
|  | 679 | +            let mut fqp_it = fqp.iter(); | 
|  | 680 | +            write!(f, "{shortty} {}", fqp_it.next().unwrap())?; | 
|  | 681 | +            for component in fqp_it { | 
|  | 682 | +                write!(f, "::{component}")?; | 
|  | 683 | +            } | 
| 793 | 684 |         } | 
| 794 |  | -    } | 
| 795 |  | -    buf.into_inner() | 
|  | 685 | +        Ok(()) | 
|  | 686 | +    }) | 
|  | 687 | +    .to_string() | 
| 796 | 688 | } | 
| 797 | 689 | 
 | 
| 798 | 690 | /// Used to render a [`clean::Path`]. | 
| @@ -954,7 +846,7 @@ pub(crate) fn anchor<'a: 'cx, 'cx>( | 
| 954 | 846 |                 text = EscapeBodyText(text.as_str()), | 
| 955 | 847 |             ) | 
| 956 | 848 |         } else { | 
| 957 |  | -            f.write_str(text.as_str()) | 
|  | 849 | +            write!(f, "{text}") | 
| 958 | 850 |         } | 
| 959 | 851 |     }) | 
| 960 | 852 | } | 
| @@ -1533,53 +1425,51 @@ impl clean::FnDecl { | 
| 1533 | 1425 | } | 
| 1534 | 1426 | 
 | 
| 1535 | 1427 | pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( | 
| 1536 |  | -    item: &clean::Item, | 
|  | 1428 | +    item: &'a clean::Item, | 
| 1537 | 1429 |     cx: &'a Context<'tcx>, | 
| 1538 | 1430 | ) -> impl Display + 'a + Captures<'tcx> { | 
| 1539 |  | -    use std::fmt::Write as _; | 
| 1540 |  | -    let vis: Cow<'static, str> = match item.visibility(cx.tcx()) { | 
| 1541 |  | -        None => "".into(), | 
| 1542 |  | -        Some(ty::Visibility::Public) => "pub ".into(), | 
| 1543 |  | -        Some(ty::Visibility::Restricted(vis_did)) => { | 
| 1544 |  | -            // FIXME(camelid): This may not work correctly if `item_did` is a module. | 
| 1545 |  | -            //                 However, rustdoc currently never displays a module's | 
| 1546 |  | -            //                 visibility, so it shouldn't matter. | 
| 1547 |  | -            let parent_module = find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id()); | 
| 1548 |  | - | 
| 1549 |  | -            if vis_did.is_crate_root() { | 
| 1550 |  | -                "pub(crate) ".into() | 
| 1551 |  | -            } else if parent_module == Some(vis_did) { | 
| 1552 |  | -                // `pub(in foo)` where `foo` is the parent module | 
| 1553 |  | -                // is the same as no visibility modifier | 
| 1554 |  | -                "".into() | 
| 1555 |  | -            } else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) | 
| 1556 |  | -                == Some(vis_did) | 
| 1557 |  | -            { | 
| 1558 |  | -                "pub(super) ".into() | 
| 1559 |  | -            } else { | 
| 1560 |  | -                let path = cx.tcx().def_path(vis_did); | 
| 1561 |  | -                debug!("path={path:?}"); | 
| 1562 |  | -                // modified from `resolved_path()` to work with `DefPathData` | 
| 1563 |  | -                let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); | 
| 1564 |  | -                let anchor = anchor(vis_did, last_name, cx); | 
| 1565 |  | - | 
| 1566 |  | -                let mut s = "pub(in ".to_owned(); | 
| 1567 |  | -                for seg in &path.data[..path.data.len() - 1] { | 
| 1568 |  | -                    let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); | 
| 1569 |  | -                } | 
| 1570 |  | -                let _ = write!(s, "{anchor}) "); | 
| 1571 |  | -                s.into() | 
| 1572 |  | -            } | 
| 1573 |  | -        } | 
| 1574 |  | -    }; | 
| 1575 |  | - | 
| 1576 | 1431 |     let is_doc_hidden = item.is_doc_hidden(); | 
| 1577 | 1432 |     fmt::from_fn(move |f| { | 
| 1578 | 1433 |         if is_doc_hidden { | 
| 1579 | 1434 |             f.write_str("#[doc(hidden)] ")?; | 
| 1580 | 1435 |         } | 
| 1581 | 1436 | 
 | 
| 1582 |  | -        f.write_str(&vis) | 
|  | 1437 | +        match item.visibility(cx.tcx()) { | 
|  | 1438 | +            None => Ok(()), | 
|  | 1439 | +            Some(ty::Visibility::Public) => f.write_str("pub "), | 
|  | 1440 | +            Some(ty::Visibility::Restricted(vis_did)) => { | 
|  | 1441 | +                // FIXME(camelid): This may not work correctly if `item_did` is a module. | 
|  | 1442 | +                //                 However, rustdoc currently never displays a module's | 
|  | 1443 | +                //                 visibility, so it shouldn't matter. | 
|  | 1444 | +                let parent_module = | 
|  | 1445 | +                    find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id()); | 
|  | 1446 | + | 
|  | 1447 | +                if vis_did.is_crate_root() { | 
|  | 1448 | +                    f.write_str("pub(crate) ") | 
|  | 1449 | +                } else if parent_module == Some(vis_did) { | 
|  | 1450 | +                    // `pub(in foo)` where `foo` is the parent module | 
|  | 1451 | +                    // is the same as no visibility modifier | 
|  | 1452 | +                    Ok(()) | 
|  | 1453 | +                } else if parent_module | 
|  | 1454 | +                    .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) | 
|  | 1455 | +                    == Some(vis_did) | 
|  | 1456 | +                { | 
|  | 1457 | +                    f.write_str("pub(super) ") | 
|  | 1458 | +                } else { | 
|  | 1459 | +                    let path = cx.tcx().def_path(vis_did); | 
|  | 1460 | +                    debug!("path={path:?}"); | 
|  | 1461 | +                    // modified from `resolved_path()` to work with `DefPathData` | 
|  | 1462 | +                    let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); | 
|  | 1463 | +                    let anchor = anchor(vis_did, last_name, cx); | 
|  | 1464 | + | 
|  | 1465 | +                    f.write_str("pub(in ")?; | 
|  | 1466 | +                    for seg in &path.data[..path.data.len() - 1] { | 
|  | 1467 | +                        write!(f, "{}::", seg.data.get_opt_name().unwrap())?; | 
|  | 1468 | +                    } | 
|  | 1469 | +                    write!(f, "{anchor}) ") | 
|  | 1470 | +                } | 
|  | 1471 | +            } | 
|  | 1472 | +        } | 
| 1583 | 1473 |     }) | 
| 1584 | 1474 | } | 
| 1585 | 1475 | 
 | 
|  | 
0 commit comments