Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6e00231
opt-dist: rebuild rustc when doing static LLVM builds
ognevny Jul 19, 2025
a6f2666
std/sys/fd: remove `- 1` from `READ_LIMIT` on Darwin
morinmorin Jul 25, 2025
9449b78
show a trailing comma on singleton tuple constructors in witness pats
dianne Aug 10, 2025
8f649a7
clean up witness printing for tuple-like constructors
dianne Aug 10, 2025
c9ce45c
Optimize `char::encode_utf8`
Kmeakin Aug 16, 2025
e8ae1da
next-solver fix const_trait_impl bootstrap
lcnr Aug 21, 2025
df3d797
Remove `dirs-sys-0.4.1` dependency.
nnethercote Aug 21, 2025
c54db96
Remove `toml-0.5.11` dependency.
nnethercote Aug 21, 2025
78bdd86
miri: also detect aliasing of in-place argument and return place
RalfJung Aug 22, 2025
7046ce8
interpret/allocation: get_range on ProvenanceMap
nia-e Jul 16, 2025
b244f29
remove default opts from config
Shourya742 Aug 23, 2025
32b193c
Remove profile section from Clippy
Kobzol Aug 23, 2025
3ac32ca
rustdoc: make attributes render consistently
karolzwolak Aug 22, 2025
90aa25a
rustdoc: update attribute tests
karolzwolak Aug 22, 2025
1c03ae1
port attribute to the new parsing infrastructure
jdonszelmann Aug 20, 2025
d8b40bd
citool: cleanup `mismatched_lifetime_syntaxes` warnings
samueltardieu Aug 23, 2025
323e230
Fix ICE when validating transmuting ZST to inhabited enum
samueltardieu Aug 23, 2025
f5210f2
Rollup merge of #143898 - ognevny:opt-dist-rustc-rebuild, r=Kobzol
samueltardieu Aug 23, 2025
982b022
Rollup merge of #144452 - morinmorin:apple/update_read_limit, r=Chris…
samueltardieu Aug 23, 2025
5a14685
Rollup merge of #145234 - dianne:1-tuple-witnesses, r=jackh726
samueltardieu Aug 23, 2025
1b9ae8f
Rollup merge of #145515 - Kmeakin:km/optimize-char-encode-utf8, r=Mar…
samueltardieu Aug 23, 2025
95f8b91
Rollup merge of #145540 - nia-e:prov-map-range, r=RalfJung
samueltardieu Aug 23, 2025
e7dc14e
Rollup merge of #145670 - jdonszelmann:port-sanitize, r=lcnr
samueltardieu Aug 23, 2025
9847cb2
Rollup merge of #145713 - lcnr:const-trait-bootstrap, r=compiler-errors
samueltardieu Aug 23, 2025
9088d7a
Rollup merge of #145729 - nnethercote:dup-packages, r=calebcartwright
samueltardieu Aug 23, 2025
0b8d7b1
Rollup merge of #145744 - RalfJung:miri-inplace-aliasing, r=compiler-…
samueltardieu Aug 23, 2025
608271f
Rollup merge of #145774 - Shourya742:2025-08-23-remove-default-opts-m…
samueltardieu Aug 23, 2025
ec52c9c
Rollup merge of #145781 - Kobzol:clippy-remove-profile, r=lqd
samueltardieu Aug 23, 2025
cc90b4f
Rollup merge of #145782 - karolzwolak:rustdoc-consistent-attributes-r…
samueltardieu Aug 23, 2025
a1cdd14
Rollup merge of #145787 - samueltardieu:push-vovspkkxsxtn, r=Kobzol
samueltardieu Aug 23, 2025
4d38062
Rollup merge of #145791 - samueltardieu:fix-zst-to-enum-mir-validatio…
samueltardieu Aug 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
rustdoc: make attributes render consistently
* make attributes render inside code elements and inside divs with class `code-attribute`
* render attributes for macros, associated constants, and struct/union fields
  • Loading branch information
karolzwolak committed Aug 23, 2025
commit 3ac32cace1df3edfd559c77bf2922c915253fbc0
37 changes: 19 additions & 18 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ fn assoc_const(
) -> impl fmt::Display {
let tcx = cx.tcx();
fmt::from_fn(move |w| {
render_attributes_in_code(w, it, &" ".repeat(indent), cx);
write!(
w,
"{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
Expand Down Expand Up @@ -1136,10 +1137,10 @@ fn assoc_method(
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
header_len += 4;
let indent_str = " ";
write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx))?;
render_attributes_in_code(w, meth, indent_str, cx);
(4, indent_str, Ending::NoNewline)
} else {
render_attributes_in_code(w, meth, cx);
render_attributes_in_code(w, meth, "", cx);
(0, "", Ending::Newline)
};
write!(
Expand Down Expand Up @@ -1309,28 +1310,28 @@ fn render_assoc_item(
})
}

// When an attribute is rendered inside a `<pre>` tag, it is formatted using
// a whitespace prefix and newline.
fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
fmt::from_fn(move |f| {
for a in it.attributes(cx.tcx(), cx.cache()) {
writeln!(f, "{prefix}{a}")?;
}
Ok(())
})
}

struct CodeAttribute(String);

fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
write!(w, "<div class=\"code-attribute\">{}</div>", code_attr.0).unwrap();
fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) {
write!(
w,
"<div class=\"code-attribute\">{prefix}{attr}</div>",
prefix = prefix,
attr = code_attr.0
)
.unwrap();
}

// When an attribute is rendered inside a <code> tag, it is formatted using
// a div to produce a newline after it.
fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
fn render_attributes_in_code(
w: &mut impl fmt::Write,
it: &clean::Item,
prefix: &str,
cx: &Context<'_>,
) {
for attr in it.attributes(cx.tcx(), cx.cache()) {
render_code_attribute(CodeAttribute(attr), w);
render_code_attribute(prefix, CodeAttribute(attr), w);
}
}

Expand All @@ -1342,7 +1343,7 @@ fn render_repr_attributes_in_code(
item_type: ItemType,
) {
if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
render_code_attribute(CodeAttribute(repr), w);
render_code_attribute("", CodeAttribute(repr), w);
}
}

Expand Down
100 changes: 49 additions & 51 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use super::{
AssocItemLink, AssocItemRender, Context, ImplRenderingParameters, RenderMode,
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
render_assoc_item, render_assoc_items, render_attributes_in_code, render_impl,
render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
render_stability_since_raw_with_extra, write_section_heading,
};
use crate::clean;
Expand Down Expand Up @@ -107,13 +107,6 @@ macro_rules! item_template_methods {
}
item_template_methods!($($rest)*);
};
(render_attributes_in_pre $($rest:tt)*) => {
fn render_attributes_in_pre(&self) -> impl fmt::Display {
let (item, cx) = self.item_and_cx();
render_attributes_in_pre(item, "", cx)
}
item_template_methods!($($rest)*);
};
(render_assoc_items $($rest:tt)*) => {
fn render_assoc_items(&self) -> impl fmt::Display {
let (item, cx) = self.item_and_cx();
Expand Down Expand Up @@ -457,7 +450,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
write!(
w,
"<dt{id}>\
<code>{vis}{imp}</code>{stab_tags}\
<code>"
)?;
render_attributes_in_code(w, myitem, "", cx);
write!(
w,
"{vis}{imp}</code>{stab_tags}\
</dt>",
vis = visibility_print_with_space(myitem, cx),
imp = import.print(cx)
Expand Down Expand Up @@ -625,11 +623,11 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();

wrap_item(w, |w| {
render_attributes_in_code(w, it, "", cx);
write!(
w,
"{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \
"{vis}{constness}{asyncness}{safety}{abi}fn \
{name}{generics}{decl}{notable_traits}{where_clause}",
attrs = render_attributes_in_pre(it, "", cx),
vis = visibility,
constness = constness,
asyncness = asyncness,
Expand Down Expand Up @@ -666,10 +664,10 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:

// Output the trait definition
wrap_item(w, |mut w| {
render_attributes_in_code(&mut w, it, "", cx);
write!(
w,
"{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
attrs = render_attributes_in_pre(it, "", cx),
"{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
vis = visibility_print_with_space(it, cx),
safety = t.safety(tcx).print_with_space(),
is_auto = if t.is_auto(tcx) { "auto " } else { "" },
Expand Down Expand Up @@ -1240,10 +1238,10 @@ fn item_trait_alias(
) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
render_attributes_in_code(w, it, "", cx);
write!(
w,
"{attrs}trait {name}{generics} = {bounds}{where_clause};",
attrs = render_attributes_in_pre(it, "", cx),
"trait {name}{generics} = {bounds}{where_clause};",
name = it.name.unwrap(),
generics = t.generics.print(cx),
bounds = print_bounds(&t.bounds, true, cx),
Expand All @@ -1268,10 +1266,10 @@ fn item_trait_alias(
fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
render_attributes_in_code(w, it, "", cx);
write!(
w,
"{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
attrs = render_attributes_in_pre(it, "", cx),
"{vis}type {name}{generics}{where_clause} = {type_};",
vis = visibility_print_with_space(it, cx),
name = it.name.unwrap(),
generics = t.generics.print(cx),
Expand Down Expand Up @@ -1452,7 +1450,14 @@ item_template!(

impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
fn render_union(&self) -> impl Display {
render_union(self.it, Some(self.generics), self.fields, self.cx)
render_union(
self.it,
Some(self.generics),
self.fields,
self.def_id,
self.is_type_alias,
self.cx,
)
}

fn document_field(&self, field: &'a clean::Item) -> impl Display {
Expand All @@ -1479,27 +1484,6 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
_ => None,
})
}

fn render_attributes_in_pre(&self) -> impl fmt::Display {
fmt::from_fn(move |f| {
if self.is_type_alias {
// For now the only attributes we render for type aliases are `repr` attributes.
if let Some(repr) = clean::repr_attributes(
self.cx.tcx(),
self.cx.cache(),
self.def_id,
ItemType::Union,
) {
writeln!(f, "{repr}")?;
};
} else {
for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) {
writeln!(f, "{a}")?;
}
}
Ok(())
})
}
}

fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
Expand Down Expand Up @@ -1563,7 +1547,7 @@ impl<'clean> DisplayEnum<'clean> {
// For now the only attributes we render for type aliases are `repr` attributes.
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum);
} else {
render_attributes_in_code(w, it, cx);
render_attributes_in_code(w, it, "", cx);
}
write!(
w,
Expand Down Expand Up @@ -1702,7 +1686,7 @@ fn render_enum_fields(
if v.is_stripped() {
continue;
}
write!(w, "{}", render_attributes_in_pre(v, TAB, cx))?;
render_attributes_in_code(w, v, TAB, cx);
w.write_str(TAB)?;
match v.kind {
clean::VariantItem(ref var) => match var.kind {
Expand Down Expand Up @@ -1882,6 +1866,7 @@ fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt:
fmt::from_fn(|w| {
wrap_item(w, |w| {
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
render_attributes_in_code(w, it, "", cx);
if !t.macro_rules {
write!(w, "{}", visibility_print_with_space(it, cx))?;
}
Expand Down Expand Up @@ -1950,7 +1935,7 @@ fn item_constant(
fmt::from_fn(|w| {
wrap_item(w, |w| {
let tcx = cx.tcx();
render_attributes_in_code(w, it, cx);
render_attributes_in_code(w, it, "", cx);

write!(
w,
Expand Down Expand Up @@ -2018,7 +2003,7 @@ impl<'a> DisplayStruct<'a> {
// For now the only attributes we render for type aliases are `repr` attributes.
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct);
} else {
render_attributes_in_code(w, it, cx);
render_attributes_in_code(w, it, "", cx);
}
write!(
w,
Expand Down Expand Up @@ -2115,7 +2100,7 @@ fn item_static(
) -> impl fmt::Display {
fmt::from_fn(move |w| {
wrap_item(w, |w| {
render_attributes_in_code(w, it, cx);
render_attributes_in_code(w, it, "", cx);
write!(
w,
"{vis}{safe}static {mutability}{name}: {typ}",
Expand All @@ -2135,7 +2120,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
fmt::from_fn(|w| {
wrap_item(w, |w| {
w.write_str("extern {\n")?;
render_attributes_in_code(w, it, cx);
render_attributes_in_code(w, it, "", cx);
write!(w, " {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),)
})?;

Expand Down Expand Up @@ -2358,9 +2343,17 @@ fn render_union(
it: &clean::Item,
g: Option<&clean::Generics>,
fields: &[clean::Item],
def_id: DefId,
is_type_alias: bool,
cx: &Context<'_>,
) -> impl Display {
fmt::from_fn(move |mut f| {
if is_type_alias {
// For now the only attributes we render for type aliases are `repr` attributes.
render_repr_attributes_in_code(f, cx, def_id, ItemType::Union);
} else {
render_attributes_in_code(f, it, "", cx);
}
write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;

let where_displayed = if let Some(generics) = g {
Expand Down Expand Up @@ -2390,6 +2383,7 @@ fn render_union(

for field in fields {
if let clean::StructFieldItem(ref ty) = field.kind {
render_attributes_in_code(&mut f, field, " ", cx);
writeln!(
f,
" {}{}: {},",
Expand Down Expand Up @@ -2481,11 +2475,15 @@ fn render_struct_fields(
if toggle {
toggle_open(&mut *w, format_args!("{count_fields} fields"));
}
if has_visible_fields {
writeln!(w)?;
}
for field in fields {
if let clean::StructFieldItem(ref ty) = field.kind {
write!(
render_attributes_in_code(w, field, &format!("{tab} "), cx);
writeln!(
w,
"\n{tab} {vis}{name}: {ty},",
"{tab} {vis}{name}: {ty},",
vis = visibility_print_with_space(field, cx),
name = field.name.unwrap(),
ty = ty.print(cx)
Expand All @@ -2495,12 +2493,12 @@ fn render_struct_fields(

if has_visible_fields {
if has_stripped_entries {
write!(
writeln!(
w,
"\n{tab} <span class=\"comment\">/* private fields */</span>"
"{tab} <span class=\"comment\">/* private fields */</span>"
)?;
}
write!(w, "\n{tab}")?;
write!(w, "{tab}")?;
} else if has_stripped_entries {
write!(w, " <span class=\"comment\">/* private fields */</span> ")?;
}
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/html/templates/item_union.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<pre class="rust item-decl"><code>
{{ self.render_attributes_in_pre()|safe }}
{{ self.render_union()|safe }}
</code></pre>
{% if !self.is_type_alias %}
Expand Down