Skip to content

Commit 4f3dd7b

Browse files
Tweak attribute rendering depending on wether or not it is a type alias
1 parent eb9f054 commit 4f3dd7b

4 files changed

Lines changed: 173 additions & 80 deletions

File tree

‎src/librustdoc/clean/types.rs‎

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -815,67 +815,7 @@ impl Item {
815815

816816
/// Returns a `#[repr(...)]` representation.
817817
pub(crate)fnrepr(&self,tcx:TyCtxt<'_>,cache:&Cache,is_json:bool) -> Option<String>{
818-
use rustc_abi::IntegerType;
819-
820-
let def_id = self.def_id()?;
821-
if !matches!(self.type_(),ItemType::Struct | ItemType::Enum | ItemType::Union){
822-
returnNone;
823-
}
824-
let adt = tcx.adt_def(def_id);
825-
let repr = adt.repr();
826-
letmut out = Vec::new();
827-
if repr.c(){
828-
out.push("C");
829-
}
830-
if repr.transparent(){
831-
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
832-
// field is public in case all fields are 1-ZST fields.
833-
let render_transparent = is_json
834-
|| cache.document_private
835-
|| adt
836-
.all_fields()
837-
.find(|field| {
838-
let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
839-
tcx.layout_of(
840-
ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty),
841-
)
842-
.is_ok_and(|layout| !layout.is_1zst())
843-
})
844-
.map_or_else(
845-
|| adt.all_fields().any(|field| field.vis.is_public()),
846-
|field| field.vis.is_public(),
847-
);
848-
849-
if render_transparent {
850-
out.push("transparent");
851-
}
852-
}
853-
if repr.simd(){
854-
out.push("simd");
855-
}
856-
let pack_s;
857-
ifletSome(pack) = repr.pack{
858-
pack_s = format!("packed({})", pack.bytes());
859-
out.push(&pack_s);
860-
}
861-
let align_s;
862-
ifletSome(align) = repr.align{
863-
align_s = format!("align({})", align.bytes());
864-
out.push(&align_s);
865-
}
866-
let int_s;
867-
ifletSome(int) = repr.int{
868-
int_s = match int {
869-
IntegerType::Pointer(is_signed) => {
870-
format!("{}size",if is_signed {'i'} else {'u'})
871-
}
872-
IntegerType::Fixed(size, is_signed) => {
873-
format!("{}{}",if is_signed {'i'} else {'u'}, size.size().bytes()*8)
874-
}
875-
};
876-
out.push(&int_s);
877-
}
878-
if !out.is_empty(){Some(format!("#[repr({})]", out.join(", ")))}else{None}
818+
repr_attributes(tcx, cache,self.def_id()?,self.type_(), is_json)
879819
}
880820

881821
pubfnis_doc_hidden(&self) -> bool{
@@ -887,6 +827,73 @@ impl Item {
887827
}
888828
}
889829

830+
pub(crate)fnrepr_attributes(
831+
tcx:TyCtxt<'_>,
832+
cache:&Cache,
833+
def_id:DefId,
834+
item_type:ItemType,
835+
is_json:bool,
836+
) -> Option<String>{
837+
use rustc_abi::IntegerType;
838+
839+
if !matches!(item_type,ItemType::Struct | ItemType::Enum | ItemType::Union){
840+
returnNone;
841+
}
842+
let adt = tcx.adt_def(def_id);
843+
let repr = adt.repr();
844+
letmut out = Vec::new();
845+
if repr.c(){
846+
out.push("C");
847+
}
848+
if repr.transparent(){
849+
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
850+
// field is public in case all fields are 1-ZST fields.
851+
let render_transparent = cache.document_private
852+
|| is_json
853+
|| adt
854+
.all_fields()
855+
.find(|field| {
856+
let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
857+
tcx.layout_of(ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty))
858+
.is_ok_and(|layout| !layout.is_1zst())
859+
})
860+
.map_or_else(
861+
|| adt.all_fields().any(|field| field.vis.is_public()),
862+
|field| field.vis.is_public(),
863+
);
864+
865+
if render_transparent {
866+
out.push("transparent");
867+
}
868+
}
869+
if repr.simd(){
870+
out.push("simd");
871+
}
872+
let pack_s;
873+
ifletSome(pack) = repr.pack{
874+
pack_s = format!("packed({})", pack.bytes());
875+
out.push(&pack_s);
876+
}
877+
let align_s;
878+
ifletSome(align) = repr.align{
879+
align_s = format!("align({})", align.bytes());
880+
out.push(&align_s);
881+
}
882+
let int_s;
883+
ifletSome(int) = repr.int{
884+
int_s = match int {
885+
IntegerType::Pointer(is_signed) => {
886+
format!("{}size",if is_signed {'i'} else {'u'})
887+
}
888+
IntegerType::Fixed(size, is_signed) => {
889+
format!("{}{}",if is_signed {'i'} else {'u'}, size.size().bytes()*8)
890+
}
891+
};
892+
out.push(&int_s);
893+
}
894+
if !out.is_empty(){Some(format!("#[repr({})]", out.join(", ")))}else{None}
895+
}
896+
890897
#[derive(Clone,Debug)]
891898
pub(crate)enumItemKind{
892899
ExternCrateItem{

‎src/librustdoc/html/render/mod.rs‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,11 +1201,31 @@ fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) ->
12011201
})
12021202
}
12031203

1204+
structCodeAttribute(String);
1205+
1206+
implCodeAttribute{
1207+
fnrender_into(self,w:&mutimpl fmt::Write){
1208+
write!(w,"<div class=\"code-attribute\">{}</div>",self.0).unwrap();
1209+
}
1210+
}
1211+
12041212
// When an attribute is rendered inside a <code> tag, it is formatted using
12051213
// a div to produce a newline after it.
12061214
fnrender_attributes_in_code(w:&mutimpl fmt::Write,it:&clean::Item,cx:&Context<'_>){
12071215
for attr in it.attributes_and_repr(cx.tcx(), cx.cache(),false){
1208-
write!(w,"<div class=\"code-attribute\">{attr}</div>").unwrap();
1216+
CodeAttribute(attr).render_into(w);
1217+
}
1218+
}
1219+
1220+
/// used for type aliases to only render their `repr` attribute.
1221+
fnrender_repr_attributes_in_code(
1222+
w:&mutimpl fmt::Write,
1223+
cx:&Context<'_>,
1224+
def_id:DefId,
1225+
item_type:ItemType,
1226+
){
1227+
ifletSome(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type){
1228+
CodeAttribute(repr).render_into(w);
12091229
}
12101230
}
12111231

‎src/librustdoc/html/render/print_item.rs‎

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use super::{
2020
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
2121
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
2222
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
23-
render_impl, render_rightside, render_stability_since_raw,
23+
render_impl,render_repr_attributes_in_code,render_rightside, render_stability_since_raw,
2424
render_stability_since_raw_with_extra, write_section_heading,
2525
};
2626
usecrate::clean;
@@ -1290,12 +1290,30 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) ->
12901290
.render_into(cx, it,true, w)?;
12911291
}
12921292
clean::TypeAliasInnerType::Union{ fields } => {
1293-
ItemUnion{ cx, it, fields,generics:&t.generics,is_type_alias:true}
1294-
.render_into(w)?;
1293+
let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
1294+
let union_def_id = ty.ty_adt_def().unwrap().did();
1295+
1296+
ItemUnion{
1297+
cx,
1298+
it,
1299+
fields,
1300+
generics:&t.generics,
1301+
is_type_alias:true,
1302+
def_id: union_def_id,
1303+
}
1304+
.render_into(w)?;
12951305
}
12961306
clean::TypeAliasInnerType::Struct{ ctor_kind, fields } => {
1297-
DisplayStruct{ctor_kind:*ctor_kind,generics:&t.generics, fields }
1298-
.render_into(cx, it,true, w)?;
1307+
let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
1308+
let struct_def_id = ty.ty_adt_def().unwrap().did();
1309+
1310+
DisplayStruct{
1311+
ctor_kind:*ctor_kind,
1312+
generics:&t.generics,
1313+
fields,
1314+
def_id: struct_def_id,
1315+
}
1316+
.render_into(cx, it,true, w)?;
12991317
}
13001318
}
13011319
}else{
@@ -1417,8 +1435,9 @@ item_template!(
14171435
fields:&'a [clean::Item],
14181436
generics:&'a clean::Generics,
14191437
is_type_alias:bool,
1438+
def_id:DefId,
14201439
},
1421-
methods = [document, document_type_layout,render_attributes_in_pre,render_assoc_items]
1440+
methods = [document, document_type_layout, render_assoc_items]
14221441
);
14231442

14241443
impl<'a,'cx:'a>ItemUnion<'a,'cx>{
@@ -1449,13 +1468,41 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
14491468
})
14501469
.peekable()
14511470
}
1471+
1472+
fnrender_attributes_in_pre(&self) -> impl fmt::Display{
1473+
fmt::from_fn(move |f| {
1474+
if !self.is_type_alias{
1475+
for a inself.it.attributes_and_repr(self.cx.tcx(),self.cx.cache(),false){
1476+
writeln!(f,"{a}")?;
1477+
}
1478+
}else{
1479+
// For now we only render `repr` attributes for type aliases.
1480+
ifletSome(repr) = clean::repr_attributes(
1481+
self.cx.tcx(),
1482+
self.cx.cache(),
1483+
self.def_id,
1484+
ItemType::Union,
1485+
){
1486+
writeln!(f,"{repr}")?;
1487+
};
1488+
}
1489+
Ok(())
1490+
})
1491+
}
14521492
}
14531493

14541494
fnitem_union(cx:&Context<'_>,it:&clean::Item,s:&clean::Union) -> impl fmt::Display{
14551495
fmt::from_fn(|w| {
1456-
ItemUnion{ cx, it,fields:&s.fields,generics:&s.generics,is_type_alias:false}
1457-
.render_into(w)
1458-
.unwrap();
1496+
ItemUnion{
1497+
cx,
1498+
it,
1499+
fields:&s.fields,
1500+
generics:&s.generics,
1501+
is_type_alias:false,
1502+
def_id: it.def_id().unwrap(),
1503+
}
1504+
.render_into(w)
1505+
.unwrap();
14591506
Ok(())
14601507
})
14611508
}
@@ -1502,7 +1549,12 @@ impl<'a> DisplayEnum<'a> {
15021549
let has_stripped_entries = variants_len != variants_count;
15031550

15041551
wrap_item(w, |w| {
1505-
render_attributes_in_code(w, it, cx);
1552+
if !is_type_alias {
1553+
render_attributes_in_code(w, it, cx);
1554+
}else{
1555+
// For now we only render `repr` attributes for type aliases.
1556+
render_repr_attributes_in_code(w, cx,self.def_id,ItemType::Enum);
1557+
}
15061558
write!(
15071559
w,
15081560
"{}enum {}{}{}",
@@ -1521,19 +1573,22 @@ impl<'a> DisplayEnum<'a> {
15211573
)
15221574
})?;
15231575

1524-
if !is_type_alias {
1576+
let def_id = it.item_id.expect_def_id();
1577+
let layout_def_id = if !is_type_alias {
15251578
write!(w,"{}", document(cx, it,None,HeadingOffset::H2))?;
1526-
}
1579+
def_id
1580+
}else{
1581+
self.def_id
1582+
};
15271583

15281584
if variants_count != 0{
15291585
write!(w,"{}", item_variants(cx, it,self.variants,self.def_id))?;
15301586
}
1531-
let def_id = it.item_id.expect_def_id();
15321587
write!(
15331588
w,
15341589
"{}{}",
15351590
render_assoc_items(cx, it, def_id,AssocItemRender::All),
1536-
document_type_layout(cx,def_id)
1591+
document_type_layout(cx,layout_def_id)
15371592
)
15381593
}
15391594
}
@@ -1938,6 +1993,7 @@ struct DisplayStruct<'a> {
19381993
ctor_kind:Option<CtorKind>,
19391994
generics:&'a clean::Generics,
19401995
fields:&'a[clean::Item],
1996+
def_id:DefId,
19411997
}
19421998

19431999
impl<'a>DisplayStruct<'a>{
@@ -1949,7 +2005,12 @@ impl<'a> DisplayStruct<'a> {
19492005
w:&mutW,
19502006
) -> fmt::Result{
19512007
wrap_item(w, |w| {
1952-
render_attributes_in_code(w, it, cx);
2008+
if !is_type_alias {
2009+
render_attributes_in_code(w, it, cx);
2010+
}else{
2011+
// For now we only render `repr` attributes for type aliases.
2012+
render_repr_attributes_in_code(w, cx,self.def_id,ItemType::Struct);
2013+
}
19532014
write!(
19542015
w,
19552016
"{}",
@@ -1974,8 +2035,13 @@ impl<'a> DisplayStruct<'a> {
19742035

19752036
fnitem_struct(cx:&Context<'_>,it:&clean::Item,s:&clean::Struct) -> impl fmt::Display{
19762037
fmt::from_fn(|w| {
1977-
DisplayStruct{ctor_kind: s.ctor_kind,generics:&s.generics,fields: s.fields.as_slice()}
1978-
.render_into(cx, it,false, w)
2038+
DisplayStruct{
2039+
ctor_kind: s.ctor_kind,
2040+
generics:&s.generics,
2041+
fields: s.fields.as_slice(),
2042+
def_id: it.def_id().unwrap(),
2043+
}
2044+
.render_into(cx, it,false, w)
19792045
})
19802046
}
19812047

‎tests/rustdoc/type-layout.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub type TypeAlias = X;
6161
pubtypeGenericTypeAlias = (Generic<(u32,())>,Generic<u32>);
6262

6363
// Regression test for the rustdoc equivalent of #85103.
64-
//@ hasraw type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.'
64+
//@ hasraw type_layout/type.Edges.html 'Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.'
6565
pubtypeEdges<'a,E> = std::borrow::Cow<'a,[E]>;
6666

6767
//@ !hasraw type_layout/trait.MyTrait.html 'Size: '

0 commit comments

Comments
 (0)