Skip to content

Commit 15f6d2e

Browse files
committed
rustdoc: Move HTML-specific attr rendering code into HTML rendering mod
These functions used to be shared with the JSON backend but nowadays they aren't.
1 parent a171994 commit 15f6d2e

File tree

2 files changed

+143
-150
lines changed

2 files changed

+143
-150
lines changed

src/librustdoc/clean/types.rs

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -801,50 +801,6 @@ impl Item {
801801
Some(tcx.visibility(def_id))
802802
}
803803

804-
/// Get a list of attributes excluding `#[repr]` to display.
805-
///
806-
/// Only used by the HTML output-format.
807-
fn attributes_without_repr(&self) -> Vec<String> {
808-
self.attrs
809-
.other_attrs
810-
.iter()
811-
.filter_map(|attr| match attr {
812-
hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) => {
813-
Some(format!("#[unsafe(link_section = \"{name}\")]"))
814-
}
815-
hir::Attribute::Parsed(AttributeKind::NoMangle(..)) => {
816-
Some("#[unsafe(no_mangle)]".to_string())
817-
}
818-
hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) => {
819-
Some(format!("#[unsafe(export_name = \"{name}\")]"))
820-
}
821-
hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) => {
822-
Some("#[non_exhaustive]".to_string())
823-
}
824-
_ => None,
825-
})
826-
.collect()
827-
}
828-
829-
/// Get a list of attributes to display on this item.
830-
///
831-
/// Only used by the HTML output-format.
832-
pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache) -> Vec<String> {
833-
let mut attrs = self.attributes_without_repr();
834-
835-
if let Some(repr_attr) = self.repr(tcx, cache) {
836-
attrs.push(repr_attr);
837-
}
838-
attrs
839-
}
840-
841-
/// Returns a stringified `#[repr(...)]` attribute.
842-
///
843-
/// Only used by the HTML output-format.
844-
pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache) -> Option<String> {
845-
repr_attributes(tcx, cache, self.def_id()?, self.type_())
846-
}
847-
848804
pub fn is_doc_hidden(&self) -> bool {
849805
self.attrs.is_doc_hidden()
850806
}
@@ -854,74 +810,6 @@ impl Item {
854810
}
855811
}
856812

857-
/// Return a string representing the `#[repr]` attribute if present.
858-
///
859-
/// Only used by the HTML output-format.
860-
pub(crate) fn repr_attributes(
861-
tcx: TyCtxt<'_>,
862-
cache: &Cache,
863-
def_id: DefId,
864-
item_type: ItemType,
865-
) -> Option<String> {
866-
use rustc_abi::IntegerType;
867-
868-
if !matches!(item_type, ItemType::Struct | ItemType::Enum | ItemType::Union) {
869-
return None;
870-
}
871-
let adt = tcx.adt_def(def_id);
872-
let repr = adt.repr();
873-
let mut out = Vec::new();
874-
if repr.c() {
875-
out.push("C");
876-
}
877-
if repr.transparent() {
878-
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
879-
// field is public in case all fields are 1-ZST fields.
880-
let render_transparent = cache.document_private
881-
|| adt
882-
.all_fields()
883-
.find(|field| {
884-
let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
885-
tcx.layout_of(ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty))
886-
.is_ok_and(|layout| !layout.is_1zst())
887-
})
888-
.map_or_else(
889-
|| adt.all_fields().any(|field| field.vis.is_public()),
890-
|field| field.vis.is_public(),
891-
);
892-
893-
if render_transparent {
894-
out.push("transparent");
895-
}
896-
}
897-
if repr.simd() {
898-
out.push("simd");
899-
}
900-
let pack_s;
901-
if let Some(pack) = repr.pack {
902-
pack_s = format!("packed({})", pack.bytes());
903-
out.push(&pack_s);
904-
}
905-
let align_s;
906-
if let Some(align) = repr.align {
907-
align_s = format!("align({})", align.bytes());
908-
out.push(&align_s);
909-
}
910-
let int_s;
911-
if let Some(int) = repr.int {
912-
int_s = match int {
913-
IntegerType::Pointer(is_signed) => {
914-
format!("{}size", if is_signed { 'i' } else { 'u' })
915-
}
916-
IntegerType::Fixed(size, is_signed) => {
917-
format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
918-
}
919-
};
920-
out.push(&int_s);
921-
}
922-
if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None }
923-
}
924-
925813
#[derive(Clone, Debug)]
926814
pub(crate) enum ItemKind {
927815
ExternCrateItem {

src/librustdoc/html/render/mod.rs

Lines changed: 143 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ use askama::Template;
5151
use itertools::Either;
5252
use rustc_ast::join_path_syms;
5353
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
54-
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
54+
use rustc_hir as hir;
55+
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
5556
use rustc_hir::def_id::{DefId, DefIdSet};
5657
use rustc_hir::{ConstStability, Mutability, RustcVersion, StabilityLevel, StableSince};
5758
use rustc_middle::ty::print::PrintTraitRefExt;
@@ -1310,43 +1311,6 @@ fn render_assoc_item(
13101311
})
13111312
}
13121313

1313-
struct CodeAttribute(String);
1314-
1315-
fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) {
1316-
write!(
1317-
w,
1318-
"<div class=\"code-attribute\">{prefix}{attr}</div>",
1319-
prefix = prefix,
1320-
attr = code_attr.0
1321-
)
1322-
.unwrap();
1323-
}
1324-
1325-
// When an attribute is rendered inside a <code> tag, it is formatted using
1326-
// a div to produce a newline after it.
1327-
fn render_attributes_in_code(
1328-
w: &mut impl fmt::Write,
1329-
it: &clean::Item,
1330-
prefix: &str,
1331-
cx: &Context<'_>,
1332-
) {
1333-
for attr in it.attributes(cx.tcx(), cx.cache()) {
1334-
render_code_attribute(prefix, CodeAttribute(attr), w);
1335-
}
1336-
}
1337-
1338-
/// used for type aliases to only render their `repr` attribute.
1339-
fn render_repr_attributes_in_code(
1340-
w: &mut impl fmt::Write,
1341-
cx: &Context<'_>,
1342-
def_id: DefId,
1343-
item_type: ItemType,
1344-
) {
1345-
if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
1346-
render_code_attribute("", CodeAttribute(repr), w);
1347-
}
1348-
}
1349-
13501314
#[derive(Copy, Clone)]
13511315
enum AssocItemLink<'a> {
13521316
Anchor(Option<&'a str>),
@@ -2959,3 +2923,144 @@ fn render_call_locations<W: fmt::Write>(
29592923

29602924
w.write_str("</div>")
29612925
}
2926+
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.
2941+
fn render_attributes_in_code(
2942+
w: &mut impl fmt::Write,
2943+
item: &clean::Item,
2944+
prefix: &str,
2945+
cx: &Context<'_>,
2946+
) {
2947+
for attr in attributes(item, cx.tcx(), cx.cache()) {
2948+
render_code_attribute(prefix, CodeAttribute(attr), w);
2949+
}
2950+
}
2951+
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);
2961+
}
2962+
}
2963+
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);
2993+
}
2994+
attrs
2995+
}
2996+
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_())
3000+
}
3001+
3002+
/// Return a string representing the `#[repr]` attribute if present.
3003+
pub(crate) fn repr_attributes(
3004+
tcx: TyCtxt<'_>,
3005+
cache: &Cache,
3006+
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);
3015+
let repr = adt.repr();
3016+
let mut out = Vec::new();
3017+
if repr.c() {
3018+
out.push("C");
3019+
}
3020+
if repr.transparent() {
3021+
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
3022+
// field is public in case all fields are 1-ZST fields.
3023+
let render_transparent = cache.document_private
3024+
|| adt
3025+
.all_fields()
3026+
.find(|field| {
3027+
let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
3028+
tcx.layout_of(ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty))
3029+
.is_ok_and(|layout| !layout.is_1zst())
3030+
})
3031+
.map_or_else(
3032+
|| adt.all_fields().any(|field| field.vis.is_public()),
3033+
|field| field.vis.is_public(),
3034+
);
3035+
3036+
if render_transparent {
3037+
out.push("transparent");
3038+
}
3039+
}
3040+
if repr.simd() {
3041+
out.push("simd");
3042+
}
3043+
let pack_s;
3044+
if let Some(pack) = repr.pack {
3045+
pack_s = format!("packed({})", pack.bytes());
3046+
out.push(&pack_s);
3047+
}
3048+
let align_s;
3049+
if let Some(align) = repr.align {
3050+
align_s = format!("align({})", align.bytes());
3051+
out.push(&align_s);
3052+
}
3053+
let int_s;
3054+
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)
3061+
}
3062+
};
3063+
out.push(&int_s);
3064+
}
3065+
if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None }
3066+
}

0 commit comments

Comments
 (0)