Skip to content

Commit be581d9

Browse files
committed
Auto merge of rust-lang#116142 - GuillaumeGomez:enum-variant-display, r=fmease
[rustdoc] Show enum discrimant if it is a C-like variant Fixes rust-lang#101337. We currently display values for associated constant items in traits: ![image](https://github.com/rust-lang/rust/assets/3050060/03e566ec-c670-47b4-8ca2-b982baa7a0f4) And we also display constant values like [here](file:///home/imperio/rust/rust/build/x86_64-unknown-linux-gnu/doc/std/f32/consts/constant.E.html). I think that for coherency, we should display values of C-like enum variants. With this change, it looks like this: ![image](https://github.com/rust-lang/rust/assets/3050060/b53fbbe0-bdb1-4289-8537-f2dd4988e9ac) As for the display of the constant value itself, I used what we already have to keep coherency. We display the C-like variants value in the following scenario: 1. It is a C-like variant with a value set => all the time 2. It is a C-like variant without a value set: All other variants are C-like variants and at least one them has its value set. Here is the result in code: ```rust // Ax and Bx value will be displayed. enum A { Ax = 12, Bx, } // Ax and Bx value will not be displayed enum B { Ax, Bx, } // Bx value will not be displayed enum C { Ax(u32), Bx, } // Bx value will not be displayed, Cx value will be displayed. #[repr(u32)] enum D { Ax(u32), Bx, Cx = 12, } ``` r? `@notriddle`
2 parents 7ed044c + 1210aac commit be581d9

File tree

6 files changed

+253
-31
lines changed

6 files changed

+253
-31
lines changed

src/librustdoc/clean/types.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -2084,9 +2084,8 @@ impl Discriminant {
20842084
pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
20852085
self.expr.map(|body| rendered_const(tcx, body))
20862086
}
2087-
/// Will always be a machine readable number, without underscores or suffixes.
2088-
pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
2089-
print_evaluated_const(tcx, self.value, false).unwrap()
2087+
pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
2088+
print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
20902089
}
20912090
}
20922091

@@ -2331,7 +2330,7 @@ impl ConstantKind {
23312330
match *self {
23322331
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
23332332
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2334-
print_evaluated_const(tcx, def_id, true)
2333+
print_evaluated_const(tcx, def_id, true, true)
23352334
}
23362335
}
23372336
}

src/librustdoc/clean/utils.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
275275
pub(crate) fn print_evaluated_const(
276276
tcx: TyCtxt<'_>,
277277
def_id: DefId,
278-
underscores_and_type: bool,
278+
with_underscores: bool,
279+
with_type: bool,
279280
) -> Option<String> {
280281
tcx.const_eval_poly(def_id).ok().and_then(|val| {
281282
let ty = tcx.type_of(def_id).instantiate_identity();
@@ -284,7 +285,7 @@ pub(crate) fn print_evaluated_const(
284285
(mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
285286
(mir::ConstValue::Scalar(_), _) => {
286287
let const_ = mir::Const::from_value(val, ty);
287-
Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
288+
Some(print_const_with_custom_print_scalar(tcx, const_, with_underscores, with_type))
288289
}
289290
_ => None,
290291
}
@@ -320,32 +321,37 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
320321
fn print_const_with_custom_print_scalar<'tcx>(
321322
tcx: TyCtxt<'tcx>,
322323
ct: mir::Const<'tcx>,
323-
underscores_and_type: bool,
324+
with_underscores: bool,
325+
with_type: bool,
324326
) -> String {
325327
// Use a slightly different format for integer types which always shows the actual value.
326328
// For all other types, fallback to the original `pretty_print_const`.
327329
match (ct, ct.ty().kind()) {
328330
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
329-
if underscores_and_type {
330-
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
331+
let mut output = if with_underscores {
332+
format_integer_with_underscore_sep(&int.to_string())
331333
} else {
332334
int.to_string()
335+
};
336+
if with_type {
337+
output += ui.name_str();
333338
}
339+
output
334340
}
335341
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
336342
let ty = ct.ty();
337343
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
338344
let data = int.assert_bits(size);
339345
let sign_extended_data = size.sign_extend(data) as i128;
340-
if underscores_and_type {
341-
format!(
342-
"{}{}",
343-
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
344-
i.name_str()
345-
)
346+
let mut output = if with_underscores {
347+
format_integer_with_underscore_sep(&sign_extended_data.to_string())
346348
} else {
347349
sign_extended_data.to_string()
350+
};
351+
if with_type {
352+
output += i.name_str();
348353
}
354+
output
349355
}
350356
_ => ct.to_string(),
351357
}

src/librustdoc/html/render/print_item.rs

+91-15
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
55
use rustc_hir as hir;
66
use rustc_hir::def::CtorKind;
77
use rustc_hir::def_id::DefId;
8+
use rustc_index::IndexVec;
89
use rustc_middle::middle::stability;
910
use rustc_middle::ty::{self, TyCtxt};
1011
use rustc_span::hygiene::MacroKind;
1112
use rustc_span::symbol::{kw, sym, Symbol};
13+
use rustc_target::abi::VariantIdx;
1214
use std::cell::{RefCell, RefMut};
1315
use std::cmp::Ordering;
1416
use std::fmt;
@@ -1257,13 +1259,14 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
12571259
w,
12581260
cx,
12591261
Some(&t.generics),
1260-
variants_iter(),
1262+
&variants,
12611263
variants_count,
12621264
has_stripped_entries,
12631265
*is_non_exhaustive,
1266+
it.def_id().unwrap(),
12641267
)
12651268
});
1266-
item_variants(w, cx, it, variants_iter());
1269+
item_variants(w, cx, it, &variants);
12671270
}
12681271
clean::TypeAliasInnerType::Union { fields } => {
12691272
wrap_item(w, |w| {
@@ -1416,36 +1419,81 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
14161419
it.name.unwrap(),
14171420
e.generics.print(cx),
14181421
);
1422+
14191423
render_enum_fields(
14201424
w,
14211425
cx,
14221426
Some(&e.generics),
1423-
e.variants(),
1427+
&e.variants,
14241428
count_variants,
14251429
e.has_stripped_entries(),
14261430
it.is_non_exhaustive(),
1431+
it.def_id().unwrap(),
14271432
);
14281433
});
14291434

14301435
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
14311436

14321437
if count_variants != 0 {
1433-
item_variants(w, cx, it, e.variants());
1438+
item_variants(w, cx, it, &e.variants);
14341439
}
14351440
let def_id = it.item_id.expect_def_id();
14361441
write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
14371442
write!(w, "{}", document_type_layout(cx, def_id));
14381443
}
14391444

1440-
fn render_enum_fields<'a>(
1445+
/// It'll return true if all variants are C-like variants and if at least one of them has a value
1446+
/// set.
1447+
fn should_show_enum_discriminant(variants: &IndexVec<VariantIdx, clean::Item>) -> bool {
1448+
let mut has_variants_with_value = false;
1449+
for variant in variants {
1450+
if let clean::VariantItem(ref var) = *variant.kind &&
1451+
matches!(var.kind, clean::VariantKind::CLike)
1452+
{
1453+
has_variants_with_value |= var.discriminant.is_some();
1454+
} else {
1455+
return false;
1456+
}
1457+
}
1458+
has_variants_with_value
1459+
}
1460+
1461+
fn display_c_like_variant(
1462+
w: &mut Buffer,
1463+
cx: &mut Context<'_>,
1464+
item: &clean::Item,
1465+
variant: &clean::Variant,
1466+
index: VariantIdx,
1467+
should_show_enum_discriminant: bool,
1468+
enum_def_id: DefId,
1469+
) {
1470+
let name = item.name.unwrap();
1471+
if let Some(ref value) = variant.discriminant {
1472+
write!(w, "{} = {}", name.as_str(), value.value(cx.tcx(), true));
1473+
} else if should_show_enum_discriminant {
1474+
let adt_def = cx.tcx().adt_def(enum_def_id);
1475+
let discr = adt_def.discriminant_for_variant(cx.tcx(), index);
1476+
if discr.ty.is_signed() {
1477+
write!(w, "{} = {}", name.as_str(), discr.val as i128);
1478+
} else {
1479+
write!(w, "{} = {}", name.as_str(), discr.val);
1480+
}
1481+
} else {
1482+
w.write_str(name.as_str());
1483+
}
1484+
}
1485+
1486+
fn render_enum_fields(
14411487
mut w: &mut Buffer,
14421488
cx: &mut Context<'_>,
14431489
g: Option<&clean::Generics>,
1444-
variants: impl Iterator<Item = &'a clean::Item>,
1490+
variants: &IndexVec<VariantIdx, clean::Item>,
14451491
count_variants: usize,
14461492
has_stripped_entries: bool,
14471493
is_non_exhaustive: bool,
1494+
enum_def_id: DefId,
14481495
) {
1496+
let should_show_enum_discriminant = should_show_enum_discriminant(variants);
14491497
if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) {
14501498
// If there wasn't a `where` clause, we add a whitespace.
14511499
w.write_str(" ");
@@ -1461,15 +1509,24 @@ fn render_enum_fields<'a>(
14611509
toggle_open(&mut w, format_args!("{count_variants} variants"));
14621510
}
14631511
const TAB: &str = " ";
1464-
for v in variants {
1512+
for (index, v) in variants.iter_enumerated() {
1513+
if v.is_stripped() {
1514+
continue;
1515+
}
14651516
w.write_str(TAB);
1466-
let name = v.name.unwrap();
14671517
match *v.kind {
1468-
// FIXME(#101337): Show discriminant
14691518
clean::VariantItem(ref var) => match var.kind {
1470-
clean::VariantKind::CLike => w.write_str(name.as_str()),
1519+
clean::VariantKind::CLike => display_c_like_variant(
1520+
w,
1521+
cx,
1522+
v,
1523+
var,
1524+
index,
1525+
should_show_enum_discriminant,
1526+
enum_def_id,
1527+
),
14711528
clean::VariantKind::Tuple(ref s) => {
1472-
write!(w, "{name}({})", print_tuple_struct_fields(cx, s),);
1529+
write!(w, "{}({})", v.name.unwrap(), print_tuple_struct_fields(cx, s));
14731530
}
14741531
clean::VariantKind::Struct(ref s) => {
14751532
render_struct(w, v, None, None, &s.fields, TAB, false, cx);
@@ -1490,11 +1547,11 @@ fn render_enum_fields<'a>(
14901547
}
14911548
}
14921549

1493-
fn item_variants<'a>(
1550+
fn item_variants(
14941551
w: &mut Buffer,
14951552
cx: &mut Context<'_>,
14961553
it: &clean::Item,
1497-
variants: impl Iterator<Item = &'a clean::Item>,
1554+
variants: &IndexVec<VariantIdx, clean::Item>,
14981555
) {
14991556
let tcx = cx.tcx();
15001557
write!(
@@ -1507,7 +1564,11 @@ fn item_variants<'a>(
15071564
document_non_exhaustive_header(it),
15081565
document_non_exhaustive(it)
15091566
);
1510-
for variant in variants {
1567+
let should_show_enum_discriminant = should_show_enum_discriminant(variants);
1568+
for (index, variant) in variants.iter_enumerated() {
1569+
if variant.is_stripped() {
1570+
continue;
1571+
}
15111572
let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
15121573
write!(
15131574
w,
@@ -1522,7 +1583,22 @@ fn item_variants<'a>(
15221583
it.const_stable_since(tcx),
15231584
" rightside",
15241585
);
1525-
write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap());
1586+
w.write_str("<h3 class=\"code-header\">");
1587+
if let clean::VariantItem(ref var) = *variant.kind &&
1588+
let clean::VariantKind::CLike = var.kind
1589+
{
1590+
display_c_like_variant(
1591+
w,
1592+
cx,
1593+
variant,
1594+
var,
1595+
index,
1596+
should_show_enum_discriminant,
1597+
it.def_id().unwrap(),
1598+
);
1599+
} else {
1600+
w.write_str(variant.name.unwrap().as_str());
1601+
}
15261602

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

src/librustdoc/json/conversions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ impl FromWithTcx<clean::Discriminant> for Discriminant {
744744
// `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
745745
// the expr is always some.
746746
expr: disr.expr(tcx).unwrap(),
747-
value: disr.value(tcx),
747+
value: disr.value(tcx, false),
748748
}
749749
}
750750
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![crate_name = "bar"]
2+
3+
pub enum E {
4+
A = 12,
5+
B,
6+
C = 1245,
7+
}
8+
9+
pub enum F {
10+
A,
11+
B,
12+
}
13+
14+
#[repr(u32)]
15+
pub enum G {
16+
A = 12,
17+
B,
18+
C(u32),
19+
}
20+
21+
pub enum H {
22+
A,
23+
C(u32),
24+
}

0 commit comments

Comments
 (0)