diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b710311c85872..0edaf6ec1f3ff 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -9,7 +9,7 @@
use std::borrow::Cow;
use std::cell::Cell;
-use std::fmt::{self, Write};
+use std::fmt::{self, Display, Write};
use std::iter::{self, once};
use rustc_ast as ast;
@@ -276,115 +276,66 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
indent: usize,
ending: Ending,
) -> impl fmt::Display + 'a + Captures<'tcx> {
- display_fn(move |f| {
- let mut where_predicates = gens.where_predicates.iter().filter(|pred| {
- !matches!(pred, clean::WherePredicate::BoundPredicate { bounds, .. } if bounds.is_empty())
- }).map(|pred| {
- display_fn(move |f| {
- if f.alternate() {
- f.write_str(" ")?;
- } else {
- f.write_str("\n")?;
- }
-
- match pred {
- clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
- let ty_cx = ty.print(cx);
- let generic_bounds = print_generic_bounds(bounds, cx);
+ let padding_amount = indent + 4;
- if bound_params.is_empty() {
- if f.alternate() {
- write!(f, "{ty_cx:#}: {generic_bounds:#}")
- } else {
- write!(f, "{ty_cx}: {generic_bounds}")
- }
- } else {
- if f.alternate() {
- write!(
- f,
- "for<{:#}> {ty_cx:#}: {generic_bounds:#}",
- comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
- )
- } else {
- write!(
- f,
- "for<{}> {ty_cx}: {generic_bounds}",
- comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
- )
- }
- }
- }
- clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
- let mut bounds_display = String::new();
- for bound in bounds.iter().map(|b| b.print(cx)) {
- write!(bounds_display, "{bound} + ")?;
- }
- bounds_display.truncate(bounds_display.len() - " + ".len());
- write!(f, "{}: {bounds_display}", lifetime.print())
- }
- // FIXME(fmease): Render bound params.
- clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
- if f.alternate() {
- write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
- } else {
- write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
- }
- }
- }
+ display_fn(move |f| {
+ let where_preds: String = gens
+ .where_predicates
+ .iter()
+ .filter(|pred| {
+ !matches!(pred, clean::WherePredicate::BoundPredicate { bounds, .. } if bounds.is_empty())
})
- }).peekable();
+ .map(|pred| {
+ print_where_pred_helper(cx, pred, padding_amount)
+ })
+ .join(",");
- if where_predicates.peek().is_none() {
+ if where_preds.is_empty() {
return Ok(());
}
- let where_preds = comma_sep(where_predicates, false);
- let clause = if f.alternate() {
- if ending == Ending::Newline {
- format!(" where{where_preds},")
- } else {
- format!(" where{where_preds}")
- }
+ if ending == Ending::Newline {
+ write!(f, "where{where_preds},")
} else {
- let mut br_with_padding = String::with_capacity(6 * indent + 28);
- br_with_padding.push('\n');
-
- let where_indent = 3;
- let padding_amount = if ending == Ending::Newline {
- indent + 4
- } else if indent == 0 {
- 4
- } else {
- indent + where_indent + "where ".len()
- };
-
- for _ in 0..padding_amount {
- br_with_padding.push(' ');
- }
- let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
+ let indent_str = " ".repeat(indent);
+ write!(f, "\n{indent_str}where{where_preds}")
+ }
+ })
+}
- if ending == Ending::Newline {
- let mut clause = " ".repeat(indent.saturating_sub(1));
- write!(clause, "where{where_preds},")?;
- clause
- } else {
- // insert a newline after a single space but before multiple spaces at the start
- if indent == 0 {
- format!("\nwhere{where_preds}")
- } else {
- // put the first one on the same line as the 'where' keyword
- let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
+fn print_where_pred_helper<'a, 'tcx: 'a>(
+ cx: &'a Context<'tcx>,
+ pred: &'a clean::WherePredicate,
+ indent_len: usize,
+) -> impl Display + Captures<'a> + Captures<'tcx> {
+ display_fn(move |f| {
+ f.write_str("\n")?;
+ f.write_str(&" ".repeat(indent_len))?;
- let mut clause = br_with_padding;
- // +1 is for `\n`.
- clause.truncate(indent + 1 + where_indent);
+ match pred {
+ clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
+ let ty_cx = ty.print(cx);
+ let generic_bounds = print_generic_bounds(bounds, cx);
- write!(clause, "where{where_preds}")?;
- clause
+ if bound_params.is_empty() {
+ write!(f, "{ty_cx}: {generic_bounds}")
+ } else {
+ write!(
+ f,
+ "for<{}> {ty_cx}: {generic_bounds}",
+ comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
+ )
}
}
- };
- write!(f, "{clause}")
+ clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
+ let bounds_display = bounds.iter().map(|b| b.print(cx)).join(" + ");
+ write!(f, "{}: {bounds_display}", lifetime.print())
+ }
+ // FIXME(fmease): Render bound params.
+ clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
+ write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
+ }
+ }
})
}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 21c1eb631e07b..86df811874174 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -640,13 +640,16 @@ pre, .rustdoc.source .example-wrap {
background: var(--table-alt-row-background-color);
}
+.where {
+ font-size: 0.875rem;
+}
+
/* Shift "where ..." part of method or fn definition down a line */
.method .where,
.fn .where,
.where.fmt-newline {
display: block;
white-space: pre-wrap;
- font-size: 0.875rem;
}
.item-info {
diff --git a/tests/rustdoc/issue-112901-where-clause.assoc-S-impl-F.html b/tests/rustdoc/issue-112901-where-clause.assoc-S-impl-F.html
new file mode 100644
index 0000000000000..b3a3d9e6c1427
--- /dev/null
+++ b/tests/rustdoc/issue-112901-where-clause.assoc-S-impl-F.html
@@ -0,0 +1,3 @@
+type F<T> = T
+where
+ T: Clone
type F<T>
+where
+ T: Clone
pub trait Tr {
+ type F<T>
+ where
+ T: Clone;
+}
\ No newline at end of file
diff --git a/tests/rustdoc/issue-112901-where-clause.assoc-Tr-impl-F.html b/tests/rustdoc/issue-112901-where-clause.assoc-Tr-impl-F.html
new file mode 100644
index 0000000000000..cbb07a3e884f5
--- /dev/null
+++ b/tests/rustdoc/issue-112901-where-clause.assoc-Tr-impl-F.html
@@ -0,0 +1,3 @@
+pub struct A<T>(_)
+where
+ T: Copy;
\ No newline at end of file
diff --git a/tests/rustdoc/issue-112901-where-clause.structs-S.html b/tests/rustdoc/issue-112901-where-clause.structs-S.html
new file mode 100644
index 0000000000000..7b1a31d7dd471
--- /dev/null
+++ b/tests/rustdoc/issue-112901-where-clause.structs-S.html
@@ -0,0 +1,3 @@
+pub struct S
+where
+ String: Clone;
\ No newline at end of file
diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html
index 3e72ba2b74fe2..a2e76a548e260 100644
--- a/tests/rustdoc/where.SWhere_Simd_item-decl.html
+++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html
@@ -1,3 +1,3 @@
pub struct Simd<T>(_)
where
- T: MyTrait;
+ T: MyTrait;
\ No newline at end of file
diff --git a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
index e8ab061e679dd..3af87a00c4271 100644
--- a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
+++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
@@ -1,13 +1,17 @@
pub trait TraitWhere {
type Item<'a>
- where Self: 'a;
+ where
+ Self: 'a;
// Provided methods
fn func(self)
- where Self: Sized { ... }
+ where
+ Self: Sized { ... }
fn lines(self) -> Lines<Self>
- where Self: Sized { ... }
+ where
+ Self: Sized { ... }
fn merge<T>(self, a: T)
- where Self: Sized,
- T: Sized { ... }
+ where
+ Self: Sized,
+ T: Sized { ... }
}
\ No newline at end of file