Skip to content

Commit 4986379

Browse files
Rollup merge of #98256 - GuillaumeGomez:whitespace-where-clause, r=notriddle
Fix whitespace handling after where clause Fixes #97733. You can see the result [here](https://rustdoc.crud.net/imperio/whitespace-where-clause/doc/foo/index.html). r? `@jsha`
2 parents 3e802d7 + c8a5b67 commit 4986379

11 files changed

+156
-14
lines changed

src/librustdoc/html/format.rs

+4
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ impl Buffer {
146146
pub(crate) fn reserve(&mut self, additional: usize) {
147147
self.buffer.reserve(additional)
148148
}
149+
150+
pub(crate) fn len(&self) -> usize {
151+
self.buffer.len()
152+
}
149153
}
150154

151155
fn comma_sep<T: fmt::Display>(

src/librustdoc/html/render/print_item.rs

+41-14
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ struct ItemVars<'a> {
6262
src_href: Option<&'a str>,
6363
}
6464

65+
/// Calls `print_where_clause` and returns `true` if a `where` clause was generated.
66+
fn print_where_clause_and_check<'a, 'tcx: 'a>(
67+
buffer: &mut Buffer,
68+
gens: &'a clean::Generics,
69+
cx: &'a Context<'tcx>,
70+
) -> bool {
71+
let len_before = buffer.len();
72+
write!(buffer, "{}", print_where_clause(gens, cx, 0, true));
73+
len_before != buffer.len()
74+
}
75+
6576
pub(super) fn print_item(
6677
cx: &mut Context<'_>,
6778
item: &clean::Item,
@@ -1152,17 +1163,21 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
11521163
render_attributes_in_pre(w, it, "");
11531164
write!(
11541165
w,
1155-
"{}enum {}{}{}",
1166+
"{}enum {}{}",
11561167
it.visibility.print_with_space(it.item_id, cx),
11571168
it.name.unwrap(),
11581169
e.generics.print(cx),
1159-
print_where_clause(&e.generics, cx, 0, true),
11601170
);
1171+
if !print_where_clause_and_check(w, &e.generics, cx) {
1172+
// If there wasn't a `where` clause, we add a whitespace.
1173+
w.write_str(" ");
1174+
}
1175+
11611176
let variants_stripped = e.has_stripped_entries();
11621177
if count_variants == 0 && !variants_stripped {
1163-
w.write_str(" {}");
1178+
w.write_str("{}");
11641179
} else {
1165-
w.write_str(" {\n");
1180+
w.write_str("{\n");
11661181
let toggle = should_hide_fields(count_variants);
11671182
if toggle {
11681183
toggle_open(w, format_args!("{} variants", count_variants));
@@ -1643,13 +1658,21 @@ fn render_union(
16431658
tab: &str,
16441659
cx: &Context<'_>,
16451660
) {
1646-
write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap());
1647-
if let Some(g) = g {
1648-
write!(w, "{}", g.print(cx));
1649-
write!(w, "{}", print_where_clause(g, cx, 0, true));
1661+
write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(),);
1662+
1663+
let where_displayed = g
1664+
.map(|g| {
1665+
write!(w, "{}", g.print(cx));
1666+
print_where_clause_and_check(w, g, cx)
1667+
})
1668+
.unwrap_or(false);
1669+
1670+
// If there wasn't a `where` clause, we add a whitespace.
1671+
if !where_displayed {
1672+
w.write_str(" ");
16501673
}
16511674

1652-
write!(w, " {{\n{}", tab);
1675+
write!(w, "{{\n{}", tab);
16531676
let count_fields =
16541677
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
16551678
let toggle = should_hide_fields(count_fields);
@@ -1701,10 +1724,14 @@ fn render_struct(
17011724
}
17021725
match ty {
17031726
CtorKind::Fictive => {
1704-
if let Some(g) = g {
1705-
write!(w, "{}", print_where_clause(g, cx, 0, true),)
1727+
let where_diplayed = g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false);
1728+
1729+
// If there wasn't a `where` clause, we add a whitespace.
1730+
if !where_diplayed {
1731+
w.write_str(" {");
1732+
} else {
1733+
w.write_str("{");
17061734
}
1707-
w.write_str(" {");
17081735
let count_fields =
17091736
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
17101737
let has_visible_fields = count_fields > 0;
@@ -1759,7 +1786,7 @@ fn render_struct(
17591786
}
17601787
w.write_str(")");
17611788
if let Some(g) = g {
1762-
write!(w, "{}", print_where_clause(g, cx, 0, false),)
1789+
write!(w, "{}", print_where_clause(g, cx, 0, false));
17631790
}
17641791
// We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
17651792
if structhead {
@@ -1769,7 +1796,7 @@ fn render_struct(
17691796
CtorKind::Const => {
17701797
// Needed for PhantomData.
17711798
if let Some(g) = g {
1772-
write!(w, "{}", print_where_clause(g, cx, 0, false),)
1799+
write!(w, "{}", print_where_clause(g, cx, 0, false));
17731800
}
17741801
w.write_str(";");
17751802
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock item-decl"><pre class="rust enum"><code>pub enum Cow&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&gt; <span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt;,&#160;</span>{
2+
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
3+
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
4+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock item-decl"><pre class="rust enum"><code>pub enum Cow2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
2+
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
3+
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
4+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// This test ensures there is no whitespace before the first brace of
2+
// trait, enum, struct and union items when they have a where clause.
3+
4+
#![crate_name = "foo"]
5+
6+
// @has 'foo/trait.ToOwned.html'
7+
// @snapshot trait - '//*[@class="docblock item-decl"]'
8+
pub trait ToOwned<T>
9+
where T: Clone
10+
{
11+
type Owned;
12+
fn to_owned(&self) -> Self::Owned;
13+
fn whatever(&self) -> T;
14+
}
15+
16+
// @has 'foo/trait.ToOwned2.html'
17+
// @snapshot trait2 - '//*[@class="docblock item-decl"]'
18+
// There should be a whitespace before `{` in this case!
19+
pub trait ToOwned2<T: Clone> {
20+
type Owned;
21+
fn to_owned(&self) -> Self::Owned;
22+
fn whatever(&self) -> T;
23+
}
24+
25+
// @has 'foo/enum.Cow.html'
26+
// @snapshot enum - '//*[@class="docblock item-decl"]'
27+
pub enum Cow<'a, B: ?Sized + 'a>
28+
where
29+
B: ToOwned<Clone>,
30+
{
31+
Borrowed(&'a B),
32+
Whatever(u32),
33+
}
34+
35+
// @has 'foo/enum.Cow2.html'
36+
// @snapshot enum2 - '//*[@class="docblock item-decl"]'
37+
// There should be a whitespace before `{` in this case!
38+
pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
39+
Borrowed(&'a B),
40+
Whatever(u32),
41+
}
42+
43+
// @has 'foo/struct.Struct.html'
44+
// @snapshot struct - '//*[@class="docblock item-decl"]'
45+
pub struct Struct<'a, B: ?Sized + 'a>
46+
where
47+
B: ToOwned<Clone>,
48+
{
49+
pub a: &'a B,
50+
pub b: u32,
51+
}
52+
53+
// @has 'foo/struct.Struct2.html'
54+
// @snapshot struct2 - '//*[@class="docblock item-decl"]'
55+
// There should be a whitespace before `{` in this case!
56+
pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
57+
pub a: &'a B,
58+
pub b: u32,
59+
}
60+
61+
// @has 'foo/union.Union.html'
62+
// @snapshot union - '//*[@class="docblock item-decl"]'
63+
pub union Union<'a, B: ?Sized + 'a>
64+
where
65+
B: ToOwned<Clone>,
66+
{
67+
a: &'a B,
68+
b: u32,
69+
}
70+
71+
// @has 'foo/union.Union2.html'
72+
// @snapshot union2 - '//*[@class="docblock item-decl"]'
73+
// There should be a whitespace before `{` in this case!
74+
pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
75+
a: &'a B,
76+
b: u32,
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Struct&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&gt; <span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt;,&#160;</span>{
2+
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
3+
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
4+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Struct2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
2+
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
3+
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
4+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div class="docblock item-decl"><pre class="rust trait"><code>pub trait ToOwned&lt;T&gt; <span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,&#160;</span>{
2+
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
3+
4+
fn <a href="#tymethod.to_owned" class="fnname">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
5+
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fnname">whatever</a>(&amp;self) -&gt; T;
6+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div class="docblock item-decl"><pre class="rust trait"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
2+
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
3+
4+
fn <a href="#tymethod.to_owned" class="fnname">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
5+
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fnname">whatever</a>(&amp;self) -&gt; T;
6+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="docblock item-decl"><pre class="rust union"><code>pub union Union&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&gt; <span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt;,&#160;</span>{
2+
/* private fields */
3+
}</code></pre></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="docblock item-decl"><pre class="rust union"><code>pub union Union2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
2+
/* private fields */
3+
}</code></pre></div>

0 commit comments

Comments
 (0)