diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 4ba1665bdc9f1..9729a4eb4465a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -207,35 +207,27 @@ impl clean::GenericParamDef {
f.write_str(self.name.as_str())?;
if !bounds.is_empty() {
- if f.alternate() {
- write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
- } else {
- write!(f, ": {}", print_generic_bounds(bounds, cx))?;
- }
+ f.write_str(": ")?;
+ fmt::Display::fmt(&print_generic_bounds(bounds, cx), f)?;
}
if let Some(ref ty) = default {
- if f.alternate() {
- write!(f, " = {:#}", ty.print(cx))?;
- } else {
- write!(f, " = {}", ty.print(cx))?;
- }
+ f.write_str(" = ")?;
+ fmt::Display::fmt(&ty.print(cx), f)?;
}
Ok(())
}
clean::GenericParamDefKind::Const { ty, default, .. } => {
- if f.alternate() {
- write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
- } else {
- write!(f, "const {}: {}", self.name, ty.print(cx))?;
- }
+ write!(f, "const {}: ", self.name)?;
+ fmt::Display::fmt(&ty.print(cx), f)?;
if let Some(default) = default {
+ f.write_str(" = ")?;
if f.alternate() {
- write!(f, " = {default:#}")?;
+ write!(f, "{default}")?;
} else {
- write!(f, " = {default}")?;
+ write!(f, "{}", Escape(default))?;
}
}
@@ -281,61 +273,55 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
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 mut where_predicates = gens
+ .where_predicates
+ .iter()
+ .map(|pred| {
+ display_fn(move |f| {
+ if f.alternate() {
+ f.write_str(" ")?;
+ } else {
+ f.write_str("\n")?;
+ }
- 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!(
+ match pred {
+ clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
+ if !bound_params.is_empty() {
+ f.write_str(if f.alternate() { "for<" } else { "for<" })?;
+ fmt::Display::fmt(
+ &comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true),
f,
- "for<{}> {ty_cx}: {generic_bounds}",
- comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
- )
+ )?;
+ f.write_str(if f.alternate() { "> " } else { "> " })?;
}
+ fmt::Display::fmt(&ty.print(cx), f)?;
+ f.write_str(":")?;
+ if !bounds.is_empty() {
+ f.write_str(" ")?;
+ fmt::Display::fmt(&print_generic_bounds(bounds, cx), f)?;
+ }
+ Ok(())
}
- }
- 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} + ")?;
+ clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
+ // We don't need to check `alternate` since we can be certain that neither
+ // the lifetime nor the bounds contain any characters which need escaping.
+ write!(f, "{}:", lifetime.print())?;
+ if !bounds.is_empty() {
+ write!(f, " {}", print_generic_bounds(bounds, cx))?;
+ }
+ Ok(())
}
- bounds_display.truncate(bounds_display.len() - " + ".len());
- write!(f, "{}: {bounds_display}", lifetime.print())
- }
- clean::WherePredicate::EqPredicate { lhs, rhs } => {
- if f.alternate() {
- write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
- } else {
- write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
+ clean::WherePredicate::EqPredicate { lhs, rhs } => {
+ if f.alternate() {
+ write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
+ } else {
+ write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
+ }
}
}
- }
+ })
})
- }).peekable();
+ .peekable();
if where_predicates.peek().is_none() {
return Ok(());
@@ -429,11 +415,7 @@ impl clean::PolyTrait {
)?;
}
}
- if f.alternate() {
- write!(f, "{:#}", self.trait_.print(cx))
- } else {
- write!(f, "{}", self.trait_.print(cx))
- }
+ fmt::Display::fmt(&self.trait_.print(cx), f)
})
}
}
@@ -446,18 +428,14 @@ impl clean::GenericBound {
display_fn(move |f| match self {
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
clean::GenericBound::TraitBound(ty, modifier) => {
- let modifier_str = match modifier {
+ f.write_str(match modifier {
hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?",
hir::TraitBoundModifier::Negative => "!",
// `const` and `~const` trait bounds are experimental; don't render them.
hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "",
- };
- if f.alternate() {
- write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx))
- } else {
- write!(f, "{modifier_str}{ty}", ty = ty.print(cx))
- }
+ })?;
+ fmt::Display::fmt(&ty.print(cx), f)
}
})
}
@@ -515,11 +493,7 @@ impl clean::GenericArgs {
f.write_str(", ")?;
}
comma = true;
- if f.alternate() {
- write!(f, "{:#}", ty.print(cx))?;
- } else {
- write!(f, "{}", ty.print(cx))?;
- }
+ fmt::Display::fmt(&ty.print(cx), f)?;
}
f.write_str(")")?;
if let Some(ref ty) = *output {
@@ -1216,11 +1190,8 @@ fn fmt_type<'cx>(
Ok(())
}
clean::ImplTrait(ref bounds) => {
- if f.alternate() {
- write!(f, "impl {:#}", print_generic_bounds(bounds, cx))
- } else {
- write!(f, "impl {}", print_generic_bounds(bounds, cx))
- }
+ f.write_str("impl ")?;
+ fmt::Display::fmt(&print_generic_bounds(bounds, cx), f)
}
clean::QPath(box clean::QPathData {
ref assoc,
@@ -1323,11 +1294,9 @@ impl clean::Impl {
cx: &'a Context<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
- if f.alternate() {
- write!(f, "impl{:#} ", self.generics.print(cx))?;
- } else {
- write!(f, "impl{} ", self.generics.print(cx))?;
- }
+ f.write_str("impl")?;
+ fmt::Display::fmt(&self.generics.print(cx), f)?;
+ f.write_str(" ")?;
if let Some(ref ty) = self.trait_ {
match self.polarity {
@@ -1400,12 +1369,7 @@ impl clean::Arguments {
display_fn(move |f| {
for (i, input) in self.values.iter().enumerate() {
write!(f, "{}: ", input.name)?;
-
- if f.alternate() {
- write!(f, "{:#}", input.type_.print(cx))?;
- } else {
- write!(f, "{}", input.type_.print(cx))?;
- }
+ fmt::Display::fmt(&input.type_.print(cx), f)?;
if i + 1 < self.values.len() {
write!(f, ", ")?;
}
@@ -1782,26 +1746,16 @@ impl clean::TypeBinding {
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
f.write_str(self.assoc.name.as_str())?;
- if f.alternate() {
- write!(f, "{:#}", self.assoc.args.print(cx))?;
- } else {
- write!(f, "{}", self.assoc.args.print(cx))?;
- }
+ fmt::Display::fmt(&self.assoc.args.print(cx), f)?;
match self.kind {
clean::TypeBindingKind::Equality { ref term } => {
- if f.alternate() {
- write!(f, " = {:#}", term.print(cx))?;
- } else {
- write!(f, " = {}", term.print(cx))?;
- }
+ f.write_str(" = ")?;
+ fmt::Display::fmt(&term.print(cx), f)?;
}
clean::TypeBindingKind::Constraint { ref bounds } => {
if !bounds.is_empty() {
- if f.alternate() {
- write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
- } else {
- write!(f, ": {}", print_generic_bounds(bounds, cx))?;
- }
+ f.write_str(": ")?;
+ fmt::Display::fmt(&print_generic_bounds(bounds, cx), f)?;
}
}
}
diff --git a/tests/rustdoc/bounds-in-multiple-parts.rs b/tests/rustdoc/bounds.rs
similarity index 54%
rename from tests/rustdoc/bounds-in-multiple-parts.rs
rename to tests/rustdoc/bounds.rs
index 279e3c148887e..da09e3f2a528f 100644
--- a/tests/rustdoc/bounds-in-multiple-parts.rs
+++ b/tests/rustdoc/bounds.rs
@@ -18,3 +18,15 @@ pub trait T2 {
fn f()
where Self: Eq, Self: Eq2, T: Eq2;
}
+
+// Checking that we support empty bounds (we used to crash on empty outlives-bounds).
+// Note that we don't want to hide them since they have a semantic effect.
+// For outlives-bounds, they force the lifetime param to be early-bound instead of late-bound.
+// For trait bounds, it can affect well-formedness (see `ClauseKind::WellFormed`).
+// @has 'foo/fn.empty.html'
+// @has - '//pre[@class="rust item-decl"]' "empty<'a, T>()where T:, 'a:,"
+pub fn empty<'a, T>()
+ where
+ T:,
+ 'a:,
+{}