Skip to content

Commit 10b5596

Browse files
Rollup merge of #136784 - yotamofek:pr/rustdoc-remove-buffer-take2, r=GuillaumeGomez
Nuke `Buffer` abstraction from `librustdoc`, take 2 💣 In #136656 I found out that the for_html field in the Buffer struct was never read, and pondered if Buffer had any utility at all. `@GuillaumeGomez` said he agrees that it can be just removed. So this PR is me removing it. So, r? `@aDotInTheVoid` , maybe? Supersedes #136748
2 parents f0af030 + d99d8c2 commit 10b5596

File tree

13 files changed

+710
-648
lines changed

13 files changed

+710
-648
lines changed

src/librustdoc/html/format.rs

+9-114
Original file line numberDiff line numberDiff line change
@@ -37,113 +37,8 @@ use crate::html::render::Context;
3737
use crate::joined::Joined as _;
3838
use crate::passes::collect_intra_doc_links::UrlFragment;
3939

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-
}
40+
pub(crate) fn write_str(s: &mut String, f: fmt::Arguments<'_>) {
41+
s.write_fmt(f).unwrap();
14742
}
14843

14944
pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
@@ -772,27 +667,27 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
772667
else {
773668
return String::new();
774669
};
775-
let mut buf = Buffer::new();
670+
let mut buf = String::new();
776671
let fqp = if *shortty == ItemType::Primitive {
777672
// primitives are documented in a crate, but not actually part of it
778673
&fqp[fqp.len() - 1..]
779674
} else {
780675
fqp
781676
};
782677
if let &Some(UrlFragment::Item(id)) = fragment {
783-
write!(buf, "{} ", cx.tcx().def_descr(id));
678+
write_str(&mut buf, format_args!("{} ", cx.tcx().def_descr(id)));
784679
for component in fqp {
785-
write!(buf, "{component}::");
680+
write_str(&mut buf, format_args!("{component}::"));
786681
}
787-
write!(buf, "{}", cx.tcx().item_name(id));
682+
write_str(&mut buf, format_args!("{}", cx.tcx().item_name(id)));
788683
} else if !fqp.is_empty() {
789684
let mut fqp_it = fqp.iter();
790-
write!(buf, "{shortty} {}", fqp_it.next().unwrap());
685+
write_str(&mut buf, format_args!("{shortty} {}", fqp_it.next().unwrap()));
791686
for component in fqp_it {
792-
write!(buf, "::{component}");
687+
write_str(&mut buf, format_args!("::{component}"));
793688
}
794689
}
795-
buf.into_inner()
690+
buf
796691
}
797692

798693
/// Used to render a [`clean::Path`].

src/librustdoc/html/highlight.rs

+44-36
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_span::edition::Edition;
1414
use rustc_span::symbol::Symbol;
1515
use rustc_span::{BytePos, DUMMY_SP, Span};
1616

17-
use super::format::{self, Buffer};
17+
use super::format::{self, write_str};
1818
use crate::clean::PrimitiveType;
1919
use crate::html::escape::EscapeBodyText;
2020
use crate::html::render::{Context, LinkFromSrc};
@@ -48,7 +48,7 @@ pub(crate) enum Tooltip {
4848
/// Highlights `src` as an inline example, returning the HTML output.
4949
pub(crate) fn render_example_with_highlighting(
5050
src: &str,
51-
out: &mut Buffer,
51+
out: &mut String,
5252
tooltip: Tooltip,
5353
playground_button: Option<&str>,
5454
extra_classes: &[String],
@@ -59,61 +59,69 @@ pub(crate) fn render_example_with_highlighting(
5959
}
6060

6161
fn write_header(
62-
out: &mut Buffer,
62+
out: &mut String,
6363
class: &str,
64-
extra_content: Option<Buffer>,
64+
extra_content: Option<&str>,
6565
tooltip: Tooltip,
6666
extra_classes: &[String],
6767
) {
68-
write!(
68+
write_str(
6969
out,
70-
"<div class=\"example-wrap{}\">",
71-
match tooltip {
72-
Tooltip::Ignore => " ignore",
73-
Tooltip::CompileFail => " compile_fail",
74-
Tooltip::ShouldPanic => " should_panic",
75-
Tooltip::Edition(_) => " edition",
76-
Tooltip::None => "",
77-
},
70+
format_args!(
71+
"<div class=\"example-wrap{}\">",
72+
match tooltip {
73+
Tooltip::Ignore => " ignore",
74+
Tooltip::CompileFail => " compile_fail",
75+
Tooltip::ShouldPanic => " should_panic",
76+
Tooltip::Edition(_) => " edition",
77+
Tooltip::None => "",
78+
}
79+
),
7880
);
7981

8082
if tooltip != Tooltip::None {
8183
let edition_code;
82-
write!(
84+
write_str(
8385
out,
84-
"<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
85-
match tooltip {
86-
Tooltip::Ignore => "This example is not tested",
87-
Tooltip::CompileFail => "This example deliberately fails to compile",
88-
Tooltip::ShouldPanic => "This example panics",
89-
Tooltip::Edition(edition) => {
90-
edition_code = format!("This example runs with edition {edition}");
91-
&edition_code
86+
format_args!(
87+
"<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
88+
match tooltip {
89+
Tooltip::Ignore => "This example is not tested",
90+
Tooltip::CompileFail => "This example deliberately fails to compile",
91+
Tooltip::ShouldPanic => "This example panics",
92+
Tooltip::Edition(edition) => {
93+
edition_code = format!("This example runs with edition {edition}");
94+
&edition_code
95+
}
96+
Tooltip::None => unreachable!(),
9297
}
93-
Tooltip::None => unreachable!(),
94-
},
98+
),
9599
);
96100
}
97101

98102
if let Some(extra) = extra_content {
99-
out.push_buffer(extra);
103+
out.push_str(&extra);
100104
}
101105
if class.is_empty() {
102-
write!(
106+
write_str(
103107
out,
104-
"<pre class=\"rust{}{}\">",
105-
if extra_classes.is_empty() { "" } else { " " },
106-
extra_classes.join(" "),
108+
format_args!(
109+
"<pre class=\"rust{}{}\">",
110+
if extra_classes.is_empty() { "" } else { " " },
111+
extra_classes.join(" ")
112+
),
107113
);
108114
} else {
109-
write!(
115+
write_str(
110116
out,
111-
"<pre class=\"rust {class}{}{}\">",
112-
if extra_classes.is_empty() { "" } else { " " },
113-
extra_classes.join(" "),
117+
format_args!(
118+
"<pre class=\"rust {class}{}{}\">",
119+
if extra_classes.is_empty() { "" } else { " " },
120+
extra_classes.join(" ")
121+
),
114122
);
115123
}
116-
write!(out, "<code>");
124+
write_str(out, format_args!("<code>"));
117125
}
118126

119127
/// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None`
@@ -398,8 +406,8 @@ pub(super) fn write_code(
398406
});
399407
}
400408

401-
fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
402-
writeln!(out, "</code></pre>{}</div>", playground_button.unwrap_or_default());
409+
fn write_footer(out: &mut String, playground_button: Option<&str>) {
410+
write_str(out, format_args_nl!("</code></pre>{}</div>", playground_button.unwrap_or_default()));
403411
}
404412

405413
/// How a span of text is classified. Mostly corresponds to token kinds.

src/librustdoc/html/highlight/tests.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxIndexMap;
33
use rustc_span::create_default_session_globals_then;
44

55
use super::{DecorationInfo, write_code};
6-
use crate::html::format::Buffer;
76

87
const STYLE: &str = r#"
98
<style>
@@ -22,9 +21,9 @@ fn test_html_highlighting() {
2221
create_default_session_globals_then(|| {
2322
let src = include_str!("fixtures/sample.rs");
2423
let html = {
25-
let mut out = Buffer::new();
24+
let mut out = String::new();
2625
write_code(&mut out, src, None, None, None);
27-
format!("{STYLE}<pre><code>{}</code></pre>\n", out.into_inner())
26+
format!("{STYLE}<pre><code>{out}</code></pre>\n")
2827
};
2928
expect_file!["fixtures/sample.html"].assert_eq(&html);
3029
});
@@ -36,9 +35,9 @@ fn test_dos_backline() {
3635
let src = "pub fn foo() {\r\n\
3736
println!(\"foo\");\r\n\
3837
}\r\n";
39-
let mut html = Buffer::new();
38+
let mut html = String::new();
4039
write_code(&mut html, src, None, None, None);
41-
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
40+
expect_file!["fixtures/dos_line.html"].assert_eq(&html);
4241
});
4342
}
4443

@@ -50,19 +49,19 @@ use self::whatever;
5049
let x = super::b::foo;
5150
let y = Self::whatever;";
5251

53-
let mut html = Buffer::new();
52+
let mut html = String::new();
5453
write_code(&mut html, src, None, None, None);
55-
expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner());
54+
expect_file!["fixtures/highlight.html"].assert_eq(&html);
5655
});
5756
}
5857

5958
#[test]
6059
fn test_union_highlighting() {
6160
create_default_session_globals_then(|| {
6261
let src = include_str!("fixtures/union.rs");
63-
let mut html = Buffer::new();
62+
let mut html = String::new();
6463
write_code(&mut html, src, None, None, None);
65-
expect_file!["fixtures/union.html"].assert_eq(&html.into_inner());
64+
expect_file!["fixtures/union.html"].assert_eq(&html);
6665
});
6766
}
6867

@@ -77,8 +76,8 @@ let a = 4;";
7776
decorations.insert("example", vec![(0, 10), (11, 21)]);
7877
decorations.insert("example2", vec![(22, 32)]);
7978

80-
let mut html = Buffer::new();
79+
let mut html = String::new();
8180
write_code(&mut html, src, None, Some(&DecorationInfo(decorations)), None);
82-
expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner());
81+
expect_file!["fixtures/decorations.html"].assert_eq(&html);
8382
});
8483
}

src/librustdoc/html/layout.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
use std::fmt::{self, Display};
12
use std::path::PathBuf;
23

34
use rinja::Template;
45
use rustc_data_structures::fx::FxIndexMap;
56

67
use super::static_files::{STATIC_FILES, StaticFiles};
78
use crate::externalfiles::ExternalHtml;
8-
use crate::html::format::{Buffer, Print};
99
use crate::html::render::{StylePath, ensure_trailing_slash};
1010

1111
#[derive(Clone)]
@@ -71,7 +71,24 @@ struct PageLayout<'a> {
7171

7272
pub(crate) use crate::html::render::sidebar::filters;
7373

74-
pub(crate) fn render<T: Print, S: Print>(
74+
/// Implements [`Display`] for a function that accepts a mutable reference to a [`String`], and (optionally) writes to it.
75+
///
76+
/// The wrapped function will receive an empty string, and can modify it,
77+
/// and the `Display` implementation will write the contents of the string after the function has finished.
78+
pub(crate) struct BufDisplay<F>(pub F);
79+
80+
impl<F> Display for BufDisplay<F>
81+
where
82+
F: Fn(&mut String),
83+
{
84+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85+
let mut buf = String::new();
86+
self.0(&mut buf);
87+
f.write_str(&buf)
88+
}
89+
}
90+
91+
pub(crate) fn render<T: Display, S: Display>(
7592
layout: &Layout,
7693
page: &Page<'_>,
7794
sidebar: S,
@@ -98,8 +115,8 @@ pub(crate) fn render<T: Print, S: Print>(
98115
let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
99116
themes.sort();
100117

101-
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
102-
let sidebar = Buffer::html().to_display(sidebar);
118+
let content = t.to_string(); // Note: This must happen before making the sidebar.
119+
let sidebar = sidebar.to_string();
103120
PageLayout {
104121
static_root_path,
105122
page,

0 commit comments

Comments
 (0)