Skip to content

Commit 406e03f

Browse files
committed
Auto merge of #101386 - aDotInTheVoid:rdj-discriminant, r=GuillaumeGomez
Rustdoc-Json: Add enum discriminant Does the first part of #101337, by adding it to `clean`, but doesn't change HTML output, as 1. [No Consensus has appeared on the UI for this](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/Enum.20discriminant.20values.20in.20HTML.20output) 2. [When inlining across crates, information is lost](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/.60clean_variant_def.20.60vs.20.60clean_variant_data.60) JSON doesn't have either of these limitations. r? `@GuillaumeGomez`
2 parents 9358d09 + efbd8f6 commit 406e03f

File tree

13 files changed

+213
-21
lines changed

13 files changed

+213
-21
lines changed

src/librustdoc/clean/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,10 @@ pub(crate) fn clean_visibility(vis: ty::Visibility) -> Visibility {
17861786

17871787
pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
17881788
let kind = match variant.ctor_kind {
1789-
CtorKind::Const => Variant::CLike,
1789+
CtorKind::Const => Variant::CLike(match variant.discr {
1790+
ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
1791+
ty::VariantDiscr::Relative(_) => None,
1792+
}),
17901793
CtorKind::Fn => Variant::Tuple(
17911794
variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
17921795
),
@@ -1803,6 +1806,7 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
18031806

18041807
fn clean_variant_data<'tcx>(
18051808
variant: &hir::VariantData<'tcx>,
1809+
disr_expr: &Option<hir::AnonConst>,
18061810
cx: &mut DocContext<'tcx>,
18071811
) -> Variant {
18081812
match variant {
@@ -1813,7 +1817,10 @@ fn clean_variant_data<'tcx>(
18131817
hir::VariantData::Tuple(..) => {
18141818
Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
18151819
}
1816-
hir::VariantData::Unit(..) => Variant::CLike,
1820+
hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
1821+
expr: Some(disr.body),
1822+
value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
1823+
})),
18171824
}
18181825
}
18191826

@@ -1967,7 +1974,7 @@ fn clean_maybe_renamed_item<'tcx>(
19671974
}
19681975

19691976
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
1970-
let kind = VariantItem(clean_variant_data(&variant.data, cx));
1977+
let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
19711978
let what_rustc_thinks =
19721979
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
19731980
// don't show `pub` for variants, which are always public

src/librustdoc/clean/types.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -2098,7 +2098,7 @@ impl Enum {
20982098

20992099
#[derive(Clone, Debug)]
21002100
pub(crate) enum Variant {
2101-
CLike,
2101+
CLike(Option<Discriminant>),
21022102
Tuple(Vec<Item>),
21032103
Struct(VariantStruct),
21042104
}
@@ -2107,11 +2107,31 @@ impl Variant {
21072107
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
21082108
match *self {
21092109
Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
2110-
Self::CLike | Self::Tuple(_) => None,
2110+
Self::CLike(..) | Self::Tuple(_) => None,
21112111
}
21122112
}
21132113
}
21142114

2115+
#[derive(Clone, Debug)]
2116+
pub(crate) struct Discriminant {
2117+
// In the case of cross crate re-exports, we don't have the nessesary information
2118+
// to reconstruct the expression of the discriminant, only the value.
2119+
pub(super) expr: Option<BodyId>,
2120+
pub(super) value: DefId,
2121+
}
2122+
2123+
impl Discriminant {
2124+
/// Will be `None` in the case of cross-crate reexports, and may be
2125+
/// simplified
2126+
pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
2127+
self.expr.map(|body| print_const_expr(tcx, body))
2128+
}
2129+
/// Will always be a machine readable number, without underscores or suffixes.
2130+
pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
2131+
print_evaluated_const(tcx, self.value, false).unwrap()
2132+
}
2133+
}
2134+
21152135
/// Small wrapper around [`rustc_span::Span`] that adds helper methods
21162136
/// and enforces calling [`rustc_span::Span::source_callsite()`].
21172137
#[derive(Copy, Clone, Debug)]
@@ -2338,7 +2358,7 @@ impl ConstantKind {
23382358
match *self {
23392359
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
23402360
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
2341-
print_evaluated_const(tcx, def_id)
2361+
print_evaluated_const(tcx, def_id, true)
23422362
}
23432363
}
23442364
}

src/librustdoc/clean/utils.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,19 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
261261
}
262262
}
263263

264-
pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
264+
pub(crate) fn print_evaluated_const(
265+
tcx: TyCtxt<'_>,
266+
def_id: DefId,
267+
underscores_and_type: bool,
268+
) -> Option<String> {
265269
tcx.const_eval_poly(def_id).ok().and_then(|val| {
266270
let ty = tcx.type_of(def_id);
267271
match (val, ty.kind()) {
268272
(_, &ty::Ref(..)) => None,
269273
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
270274
(ConstValue::Scalar(_), _) => {
271275
let const_ = mir::ConstantKind::from_value(val, ty);
272-
Some(print_const_with_custom_print_scalar(tcx, const_))
276+
Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
273277
}
274278
_ => None,
275279
}
@@ -302,23 +306,35 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
302306
.collect()
303307
}
304308

305-
fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String {
309+
fn print_const_with_custom_print_scalar(
310+
tcx: TyCtxt<'_>,
311+
ct: mir::ConstantKind<'_>,
312+
underscores_and_type: bool,
313+
) -> String {
306314
// Use a slightly different format for integer types which always shows the actual value.
307315
// For all other types, fallback to the original `pretty_print_const`.
308316
match (ct, ct.ty().kind()) {
309317
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
310-
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
318+
if underscores_and_type {
319+
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
320+
} else {
321+
int.to_string()
322+
}
311323
}
312324
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
313325
let ty = tcx.lift(ct.ty()).unwrap();
314326
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
315327
let data = int.assert_bits(size);
316328
let sign_extended_data = size.sign_extend(data) as i128;
317-
format!(
318-
"{}{}",
319-
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
320-
i.name_str()
321-
)
329+
if underscores_and_type {
330+
format!(
331+
"{}{}",
332+
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
333+
i.name_str()
334+
)
335+
} else {
336+
sign_extended_data.to_string()
337+
}
322338
}
323339
_ => ct.to_string(),
324340
}

src/librustdoc/fold.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub(crate) trait DocFolder: Sized {
4646
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
4747
VariantItem(Variant::Tuple(fields))
4848
}
49-
Variant::CLike => VariantItem(Variant::CLike),
49+
Variant::CLike(disr) => VariantItem(Variant::CLike(disr)),
5050
},
5151
ExternCrateItem { src: _ }
5252
| ImportItem(_)

src/librustdoc/html/render/print_item.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,8 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
12031203
let name = v.name.unwrap();
12041204
match *v.kind {
12051205
clean::VariantItem(ref var) => match var {
1206-
clean::Variant::CLike => write!(w, "{}", name),
1206+
// FIXME(#101337): Show discriminant
1207+
clean::Variant::CLike(..) => write!(w, "{}", name),
12071208
clean::Variant::Tuple(ref s) => {
12081209
write!(w, "{}(", name);
12091210
print_tuple_struct_fields(w, cx, s);

src/librustdoc/json/conversions.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ impl FromWithTcx<clean::Variant> for Variant {
662662
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
663663
use clean::Variant::*;
664664
match variant {
665-
CLike => Variant::Plain,
665+
CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))),
666666
Tuple(fields) => Variant::Tuple(
667667
fields
668668
.into_iter()
@@ -678,6 +678,18 @@ impl FromWithTcx<clean::Variant> for Variant {
678678
}
679679
}
680680

681+
impl FromWithTcx<clean::Discriminant> for Discriminant {
682+
fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
683+
Discriminant {
684+
// expr is only none if going throught the inlineing path, which gets
685+
// `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
686+
// the expr is always some.
687+
expr: disr.expr(tcx).unwrap(),
688+
value: disr.value(tcx),
689+
}
690+
}
691+
}
692+
681693
impl FromWithTcx<clean::Import> for Import {
682694
fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
683695
use clean::ImportKind::*;

src/librustdoc/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(crate) trait DocVisitor: Sized {
2020
VariantItem(i) => match i {
2121
Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
2222
Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
23-
Variant::CLike => {}
23+
Variant::CLike(_) => {}
2424
},
2525
ExternCrateItem { src: _ }
2626
| ImportItem(_)

src/rustdoc-json-types/lib.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::path::PathBuf;
99
use serde::{Deserialize, Serialize};
1010

1111
/// rustdoc format-version.
12-
pub const FORMAT_VERSION: u32 = 18;
12+
pub const FORMAT_VERSION: u32 = 19;
1313

1414
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
1515
/// about the language items in the local crate, as well as info about external items to allow
@@ -308,11 +308,28 @@ pub struct Enum {
308308
#[serde(rename_all = "snake_case")]
309309
#[serde(tag = "variant_kind", content = "variant_inner")]
310310
pub enum Variant {
311-
Plain,
311+
Plain(Option<Discriminant>),
312312
Tuple(Vec<Type>),
313313
Struct(Vec<Id>),
314314
}
315315

316+
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
317+
pub struct Discriminant {
318+
/// The expression that produced the discriminant.
319+
///
320+
/// Unlike `value`, this preserves the original formatting (eg suffixes,
321+
/// hexadecimal, and underscores), making it unsuitable to be machine
322+
/// interpreted.
323+
///
324+
/// In some cases, when the value is to complex, this may be `"{ _ }"`.
325+
/// When this occurs is unstable, and may change without notice.
326+
pub expr: String,
327+
/// The numerical value of the discriminant. Stored as a string due to
328+
/// JSON's poor support for large integers, and the fact that it would need
329+
/// to store from [`i128::MIN`] to [`u128::MAX`].
330+
pub value: String,
331+
}
332+
316333
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
317334
#[serde(rename_all = "snake_case")]
318335
pub enum StructType {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#[repr(i8)]
2+
pub enum Ordering {
3+
// @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"'
4+
// @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"'
5+
Less = -1,
6+
// @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"'
7+
// @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"'
8+
Equal = 0,
9+
// @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"'
10+
// @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"'
11+
Greater = 1,
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
pub enum Foo {
2+
// @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"'
3+
// @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"'
4+
Addition = 0 + 0,
5+
// @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"'
6+
// @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"'
7+
Bin = 0b1,
8+
// @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"'
9+
// @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"'
10+
Oct = 0o2,
11+
// @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"'
12+
// @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"'
13+
PubConst = THREE,
14+
// @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"'
15+
// @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"'
16+
Hex = 0x4,
17+
// @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"'
18+
// @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"'
19+
Cast = 5 as isize,
20+
// @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"'
21+
// @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"'
22+
PubCall = six(),
23+
// @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"'
24+
// @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"'
25+
PrivCall = seven(),
26+
// @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"'
27+
// @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"'
28+
PrivConst = EIGHT,
29+
}
30+
31+
pub const THREE: isize = 3;
32+
const EIGHT: isize = 8;
33+
34+
pub const fn six() -> isize {
35+
6
36+
}
37+
const fn seven() -> isize {
38+
7
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// ignore-tidy-linelength
2+
#![feature(repr128)]
3+
#![allow(incomplete_features)]
4+
5+
#[repr(u64)]
6+
pub enum U64 {
7+
// @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.value" '"0"'
8+
// @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.expr" '"u64::MIN"'
9+
U64Min = u64::MIN,
10+
// @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.value" '"18446744073709551615"'
11+
// @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.expr" '"u64::MAX"'
12+
U64Max = u64::MAX,
13+
}
14+
15+
#[repr(i64)]
16+
pub enum I64 {
17+
// @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.value" '"-9223372036854775808"'
18+
// @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.expr" '"i64::MIN"'
19+
I64Min = i64::MIN,
20+
// @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.value" '"9223372036854775807"'
21+
// @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.expr" '"i64::MAX"'
22+
I64Max = i64::MAX,
23+
}
24+
25+
#[repr(u128)]
26+
pub enum U128 {
27+
// @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.value" '"0"'
28+
// @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.expr" '"u128::MIN"'
29+
U128Min = u128::MIN,
30+
// @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.value" '"340282366920938463463374607431768211455"'
31+
// @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.expr" '"u128::MAX"'
32+
U128Max = u128::MAX,
33+
}
34+
35+
#[repr(i128)]
36+
pub enum I128 {
37+
// @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.value" '"-170141183460469231731687303715884105728"'
38+
// @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.expr" '"i128::MIN"'
39+
I128Min = i128::MIN,
40+
// @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.value" '"170141183460469231731687303715884105727"'
41+
// @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.expr" '"i128::MAX"'
42+
I128Max = i128::MAX,
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#[repr(u32)]
2+
pub enum Foo {
3+
// @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.value" '"0"'
4+
// @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.expr" '"0"'
5+
Basic = 0,
6+
// @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.value" '"10"'
7+
// @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.expr" '"10u32"'
8+
Suffix = 10u32,
9+
// @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.value" '"100"'
10+
// @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.expr" '"1_0_0"'
11+
Underscore = 1_0_0,
12+
// @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.value" '"1000"'
13+
// @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.expr" '"1_0_0_0u32"'
14+
SuffixUnderscore = 1_0_0_0u32,
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub enum Foo {
2+
// @is "$.index[*][?(@.name=='Has')].inner.variant_inner" '{"expr":"0", "value":"0"}'
3+
Has = 0,
4+
// @is "$.index[*][?(@.name=='Doesnt')].inner.variant_inner" null
5+
Doesnt,
6+
// @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant_inner" null
7+
AlsoDoesnt,
8+
// @is "$.index[*][?(@.name=='AlsoHas')].inner.variant_inner" '{"expr":"44", "value":"44"}'
9+
AlsoHas = 44,
10+
}

0 commit comments

Comments
 (0)