Skip to content

Commit 88e7977

Browse files
committed
rustdoc: Slightly clean up attr rendering
1 parent 15f6d2e commit 88e7977

File tree

2 files changed

+56
-97
lines changed

2 files changed

+56
-97
lines changed

src/librustdoc/html/render/mod.rs

Lines changed: 52 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use rustc_ast::join_path_syms;
5353
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
5454
use rustc_hir as hir;
5555
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
56+
use rustc_hir::def::DefKind;
5657
use rustc_hir::def_id::{DefId, DefIdSet};
5758
use rustc_hir::{ConstStability, Mutability, RustcVersion, StabilityLevel, StableSince};
5859
use rustc_middle::ty::print::PrintTraitRefExt;
@@ -2924,99 +2925,56 @@ fn render_call_locations<W: fmt::Write>(
29242925
w.write_str("</div>")
29252926
}
29262927

2927-
struct CodeAttribute(String);
2928-
2929-
fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) {
2930-
write!(
2931-
w,
2932-
"<div class=\"code-attribute\">{prefix}{attr}</div>",
2933-
prefix = prefix,
2934-
attr = code_attr.0
2935-
)
2936-
.unwrap();
2937-
}
2938-
2939-
// When an attribute is rendered inside a <code> tag, it is formatted using
2940-
// a div to produce a newline after it.
29412928
fn render_attributes_in_code(
29422929
w: &mut impl fmt::Write,
29432930
item: &clean::Item,
29442931
prefix: &str,
29452932
cx: &Context<'_>,
29462933
) {
2947-
for attr in attributes(item, cx.tcx(), cx.cache()) {
2948-
render_code_attribute(prefix, CodeAttribute(attr), w);
2934+
for attr in &item.attrs.other_attrs {
2935+
let hir::Attribute::Parsed(kind) = attr else { continue };
2936+
let attr = match kind {
2937+
AttributeKind::LinkSection { name, .. } => {
2938+
Cow::Owned(format!("#[unsafe(link_section = \"{name}\")]"))
2939+
}
2940+
AttributeKind::NoMangle(..) => Cow::Borrowed("#[unsafe(no_mangle)]"),
2941+
AttributeKind::ExportName { name, .. } => {
2942+
Cow::Owned(format!("#[unsafe(export_name = \"{name}\")]"))
2943+
}
2944+
AttributeKind::NonExhaustive(..) => Cow::Borrowed("#[non_exhaustive]"),
2945+
_ => continue,
2946+
};
2947+
render_code_attribute(prefix, attr.as_ref(), w);
29492948
}
2950-
}
29512949

2952-
/// used for type aliases to only render their `repr` attribute.
2953-
fn render_repr_attributes_in_code(
2954-
w: &mut impl fmt::Write,
2955-
cx: &Context<'_>,
2956-
def_id: DefId,
2957-
item_type: ItemType,
2958-
) {
2959-
if let Some(repr) = repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
2960-
render_code_attribute("", CodeAttribute(repr), w);
2950+
if let Some(def_id) = item.def_id()
2951+
&& let Some(repr) = repr_attribute(cx.tcx(), cx.cache(), def_id)
2952+
{
2953+
render_code_attribute(prefix, &repr, w);
29612954
}
29622955
}
29632956

2964-
/// Get a list of attributes excluding `#[repr]` to display.
2965-
fn attributes_without_repr(item: &clean::Item) -> Vec<String> {
2966-
item.attrs
2967-
.other_attrs
2968-
.iter()
2969-
.filter_map(|attr| match attr {
2970-
hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) => {
2971-
Some(format!("#[unsafe(link_section = \"{name}\")]"))
2972-
}
2973-
hir::Attribute::Parsed(AttributeKind::NoMangle(..)) => {
2974-
Some("#[unsafe(no_mangle)]".to_string())
2975-
}
2976-
hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) => {
2977-
Some(format!("#[unsafe(export_name = \"{name}\")]"))
2978-
}
2979-
hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) => {
2980-
Some("#[non_exhaustive]".to_string())
2981-
}
2982-
_ => None,
2983-
})
2984-
.collect()
2985-
}
2986-
2987-
/// Get a list of attributes to display on this item.
2988-
fn attributes(item: &clean::Item, tcx: TyCtxt<'_>, cache: &Cache) -> Vec<String> {
2989-
let mut attrs = attributes_without_repr(item);
2990-
2991-
if let Some(repr_attr) = repr(item, tcx, cache) {
2992-
attrs.push(repr_attr);
2957+
fn render_repr_attribute_in_code(w: &mut impl fmt::Write, cx: &Context<'_>, def_id: DefId) {
2958+
if let Some(repr) = repr_attribute(cx.tcx(), cx.cache(), def_id) {
2959+
render_code_attribute("", &repr, w);
29932960
}
2994-
attrs
29952961
}
29962962

2997-
/// Returns a stringified `#[repr(...)]` attribute.
2998-
fn repr(item: &clean::Item, tcx: TyCtxt<'_>, cache: &Cache) -> Option<String> {
2999-
repr_attributes(tcx, cache, item.def_id()?, item.type_())
2963+
fn render_code_attribute(prefix: &str, attr: &str, w: &mut impl fmt::Write) {
2964+
write!(w, "<div class=\"code-attribute\">{prefix}{attr}</div>").unwrap();
30002965
}
30012966

3002-
/// Return a string representing the `#[repr]` attribute if present.
3003-
pub(crate) fn repr_attributes(
3004-
tcx: TyCtxt<'_>,
2967+
fn repr_attribute<'tcx>(
2968+
tcx: TyCtxt<'tcx>,
30052969
cache: &Cache,
30062970
def_id: DefId,
3007-
item_type: ItemType,
3008-
) -> Option<String> {
3009-
use rustc_abi::IntegerType;
3010-
3011-
if !matches!(item_type, ItemType::Struct | ItemType::Enum | ItemType::Union) {
3012-
return None;
3013-
}
3014-
let adt = tcx.adt_def(def_id);
2971+
) -> Option<Cow<'static, str>> {
2972+
let adt = match tcx.def_kind(def_id) {
2973+
DefKind::Struct | DefKind::Enum | DefKind::Union => tcx.adt_def(def_id),
2974+
_ => return None,
2975+
};
30152976
let repr = adt.repr();
3016-
let mut out = Vec::new();
3017-
if repr.c() {
3018-
out.push("C");
3019-
}
2977+
30202978
if repr.transparent() {
30212979
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
30222980
// field is public in case all fields are 1-ZST fields.
@@ -3033,34 +2991,35 @@ pub(crate) fn repr_attributes(
30332991
|field| field.vis.is_public(),
30342992
);
30352993

3036-
if render_transparent {
3037-
out.push("transparent");
3038-
}
2994+
// Since the transparent repr can't have any other reprs or
2995+
// repr modifiers beside it, we can safely return early here.
2996+
return render_transparent.then(|| "#[repr(transparent)]".into());
2997+
}
2998+
2999+
let mut result = Vec::<Cow<'_, _>>::new();
3000+
3001+
if repr.c() {
3002+
result.push("C".into());
30393003
}
30403004
if repr.simd() {
3041-
out.push("simd");
3005+
result.push("simd".into());
30423006
}
3043-
let pack_s;
30443007
if let Some(pack) = repr.pack {
3045-
pack_s = format!("packed({})", pack.bytes());
3046-
out.push(&pack_s);
3008+
result.push(format!("packed({})", pack.bytes()).into());
30473009
}
3048-
let align_s;
30493010
if let Some(align) = repr.align {
3050-
align_s = format!("align({})", align.bytes());
3051-
out.push(&align_s);
3011+
result.push(format!("align({})", align.bytes()).into());
30523012
}
3053-
let int_s;
30543013
if let Some(int) = repr.int {
3055-
int_s = match int {
3056-
IntegerType::Pointer(is_signed) => {
3057-
format!("{}size", if is_signed { 'i' } else { 'u' })
3058-
}
3059-
IntegerType::Fixed(size, is_signed) => {
3060-
format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
3014+
let prefix = if int.is_signed() { 'i' } else { 'u' };
3015+
let int = match int {
3016+
rustc_abi::IntegerType::Pointer(_) => format!("{prefix}size"),
3017+
rustc_abi::IntegerType::Fixed(int, _) => {
3018+
format!("{prefix}{}", int.size().bytes() * 8)
30613019
}
30623020
};
3063-
out.push(&int_s);
3021+
result.push(int.into());
30643022
}
3065-
if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None }
3023+
3024+
(!result.is_empty()).then(|| format!("#[repr({})]", result.join(", ")).into())
30663025
}

src/librustdoc/html/render/print_item.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use super::{
2121
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
2222
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
2323
render_assoc_item, render_assoc_items, render_attributes_in_code, render_impl,
24-
render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
24+
render_repr_attribute_in_code, render_rightside, render_stability_since_raw,
2525
render_stability_since_raw_with_extra, write_section_heading,
2626
};
2727
use crate::clean;
@@ -1555,7 +1555,7 @@ impl<'clean> DisplayEnum<'clean> {
15551555
wrap_item(w, |w| {
15561556
if is_type_alias {
15571557
// For now the only attributes we render for type aliases are `repr` attributes.
1558-
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum);
1558+
render_repr_attribute_in_code(w, cx, self.def_id);
15591559
} else {
15601560
render_attributes_in_code(w, it, "", cx);
15611561
}
@@ -2017,7 +2017,7 @@ impl<'a> DisplayStruct<'a> {
20172017
wrap_item(w, |w| {
20182018
if is_type_alias {
20192019
// For now the only attributes we render for type aliases are `repr` attributes.
2020-
render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct);
2020+
render_repr_attribute_in_code(w, cx, self.def_id);
20212021
} else {
20222022
render_attributes_in_code(w, it, "", cx);
20232023
}
@@ -2371,7 +2371,7 @@ fn render_union(
23712371
fmt::from_fn(move |mut f| {
23722372
if is_type_alias {
23732373
// For now the only attributes we render for type aliases are `repr` attributes.
2374-
render_repr_attributes_in_code(f, cx, def_id, ItemType::Union);
2374+
render_repr_attribute_in_code(f, cx, def_id);
23752375
} else {
23762376
render_attributes_in_code(f, it, "", cx);
23772377
}

0 commit comments

Comments
 (0)