Skip to content

Commit 91114d6

Browse files
Show values of C-like variants even if not defined by the user
1 parent 4a64c79 commit 91114d6

File tree

1 file changed

+90
-22
lines changed

1 file changed

+90
-22
lines changed

src/librustdoc/html/render/print_item.rs

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,13 +1257,13 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
12571257
w,
12581258
cx,
12591259
Some(&t.generics),
1260-
variants_iter(),
1260+
&variants,
12611261
variants_count,
12621262
has_stripped_entries,
12631263
*is_non_exhaustive,
12641264
)
12651265
});
1266-
item_variants(w, cx, it, variants_iter());
1266+
item_variants(w, cx, it, &variants);
12671267
}
12681268
clean::TypeAliasInnerType::Union { fields } => {
12691269
wrap_item(w, |w| {
@@ -1416,11 +1416,12 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
14161416
it.name.unwrap(),
14171417
e.generics.print(cx),
14181418
);
1419+
14191420
render_enum_fields(
14201421
w,
14211422
cx,
14221423
Some(&e.generics),
1423-
e.variants(),
1424+
&e.variants,
14241425
count_variants,
14251426
e.has_stripped_entries(),
14261427
it.is_non_exhaustive(),
@@ -1430,22 +1431,80 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
14301431
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
14311432

14321433
if count_variants != 0 {
1433-
item_variants(w, cx, it, e.variants());
1434+
item_variants(w, cx, it, &e.variants);
14341435
}
14351436
let def_id = it.item_id.expect_def_id();
14361437
write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
14371438
write!(w, "{}", document_type_layout(cx, def_id));
14381439
}
14391440

1440-
fn render_enum_fields<'a>(
1441+
fn get_parent_enum_def_id(
1442+
cx: &mut Context<'_>,
1443+
variant_def_id: rustc_hir::def_id::LocalDefId,
1444+
) -> DefId {
1445+
use rustc_hir::{ItemKind, Node};
1446+
let variant_hir_id = cx.tcx().hir().local_def_id_to_hir_id(variant_def_id);
1447+
1448+
for (_, node) in cx.tcx().hir().parent_iter(variant_hir_id) {
1449+
if let Node::Item(item) = node && matches!(item.kind, ItemKind::Enum(..)) {
1450+
return item.owner_id.to_def_id();
1451+
}
1452+
}
1453+
panic!("No parent enum found for variant {variant_def_id:?}");
1454+
}
1455+
1456+
fn is_c_like_enum(
1457+
variants: &rustc_index::IndexVec<rustc_target::abi::VariantIdx, clean::Item>,
1458+
) -> bool {
1459+
!variants.iter().any(|variant| {
1460+
matches!(
1461+
*variant.kind,
1462+
clean::VariantItem(clean::Variant {
1463+
kind: clean::VariantKind::Tuple(_) | clean::VariantKind::Struct(_),
1464+
..
1465+
})
1466+
)
1467+
})
1468+
}
1469+
1470+
fn display_c_like_variant(
1471+
w: &mut Buffer,
1472+
cx: &mut Context<'_>,
1473+
item: &clean::Item,
1474+
variant: &clean::Variant,
1475+
index: rustc_target::abi::VariantIdx,
1476+
is_c_like_enum: bool,
1477+
) {
1478+
let name = item.name.unwrap();
1479+
if let Some(ref value) = variant.discriminant {
1480+
write!(w, "{} = {}", name.as_str(), value.value(cx.tcx(), true));
1481+
} else if is_c_like_enum &&
1482+
let Some(variant_def_id) = item.item_id.as_def_id() &&
1483+
let Some(variant_def_id) = variant_def_id.as_local()
1484+
{
1485+
let enum_def_id = get_parent_enum_def_id(cx, variant_def_id);
1486+
let adt_def = cx.tcx().adt_def(enum_def_id);
1487+
let discr = adt_def.discriminant_for_variant(cx.tcx(), index);
1488+
if discr.ty.is_signed() {
1489+
write!(w, "{} = {}", name.as_str(), discr.val as i128);
1490+
} else {
1491+
write!(w, "{} = {}", name.as_str(), discr.val);
1492+
}
1493+
} else {
1494+
w.write_str(name.as_str());
1495+
}
1496+
}
1497+
1498+
fn render_enum_fields(
14411499
mut w: &mut Buffer,
14421500
cx: &mut Context<'_>,
14431501
g: Option<&clean::Generics>,
1444-
variants: impl Iterator<Item = &'a clean::Item>,
1502+
variants: &rustc_index::IndexVec<rustc_target::abi::VariantIdx, clean::Item>,
14451503
count_variants: usize,
14461504
has_stripped_entries: bool,
14471505
is_non_exhaustive: bool,
14481506
) {
1507+
let is_c_like_enum = is_c_like_enum(variants);
14491508
if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) {
14501509
// If there wasn't a `where` clause, we add a whitespace.
14511510
w.write_str(" ");
@@ -1461,21 +1520,18 @@ fn render_enum_fields<'a>(
14611520
toggle_open(&mut w, format_args!("{count_variants} variants"));
14621521
}
14631522
const TAB: &str = " ";
1464-
for v in variants {
1523+
for (index, v) in variants.iter_enumerated() {
1524+
if v.is_stripped() {
1525+
continue;
1526+
}
14651527
w.write_str(TAB);
1466-
let name = v.name.unwrap();
14671528
match *v.kind {
1468-
// FIXME(#101337): Show discriminant
14691529
clean::VariantItem(ref var) => match var.kind {
14701530
clean::VariantKind::CLike => {
1471-
if let Some(ref value) = var.discriminant {
1472-
write!(w, "{} = {}", name.as_str(), value.value(cx.tcx(), true));
1473-
} else {
1474-
w.write_str(name.as_str());
1475-
}
1531+
display_c_like_variant(w, cx, v, var, index, is_c_like_enum)
14761532
}
14771533
clean::VariantKind::Tuple(ref s) => {
1478-
write!(w, "{name}({})", print_tuple_struct_fields(cx, s));
1534+
write!(w, "{}({})", v.name.unwrap(), print_tuple_struct_fields(cx, s));
14791535
}
14801536
clean::VariantKind::Struct(ref s) => {
14811537
render_struct(w, v, None, None, &s.fields, TAB, false, cx);
@@ -1496,11 +1552,11 @@ fn render_enum_fields<'a>(
14961552
}
14971553
}
14981554

1499-
fn item_variants<'a>(
1555+
fn item_variants(
15001556
w: &mut Buffer,
15011557
cx: &mut Context<'_>,
15021558
it: &clean::Item,
1503-
variants: impl Iterator<Item = &'a clean::Item>,
1559+
variants: &rustc_index::IndexVec<rustc_target::abi::VariantIdx, clean::Item>,
15041560
) {
15051561
let tcx = cx.tcx();
15061562
write!(
@@ -1513,7 +1569,11 @@ fn item_variants<'a>(
15131569
document_non_exhaustive_header(it),
15141570
document_non_exhaustive(it)
15151571
);
1516-
for variant in variants {
1572+
let is_c_like_enum = is_c_like_enum(variants);
1573+
for (index, variant) in variants.iter_enumerated() {
1574+
if variant.is_stripped() {
1575+
continue;
1576+
}
15171577
let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
15181578
write!(
15191579
w,
@@ -1528,12 +1588,20 @@ fn item_variants<'a>(
15281588
it.const_stable_since(tcx),
15291589
" rightside",
15301590
);
1531-
write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap());
1591+
w.write_str("<h3 class=\"code-header\">");
15321592
if let clean::VariantItem(ref var) = *variant.kind &&
1533-
let clean::VariantKind::CLike = var.kind &&
1534-
let Some(ref value) = var.discriminant
1593+
let clean::VariantKind::CLike = var.kind
15351594
{
1536-
write!(w, " = {}", value.value(cx.tcx(), true));
1595+
display_c_like_variant(
1596+
w,
1597+
cx,
1598+
variant,
1599+
var,
1600+
index,
1601+
is_c_like_enum,
1602+
);
1603+
} else {
1604+
w.write_str(variant.name.unwrap().as_str());
15371605
}
15381606

15391607
let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() };

0 commit comments

Comments
 (0)