Skip to content

Commit

Permalink
Rollup merge of #106354 - aDotInTheVoid:rdj-always-discr, r=Guillaume…
Browse files Browse the repository at this point in the history
…Gomez

Rustdoc-Json: Report discriminant on all kinds of enum variant.

Closes #106299

Probably easier to review one commit at a time.

r? `@GuillaumeGomez`
  • Loading branch information
compiler-errors authored Jan 2, 2023
2 parents 0670a61 + cca5d21 commit 0d5c5fa
Show file tree
Hide file tree
Showing 22 changed files with 257 additions and 201 deletions.
42 changes: 27 additions & 15 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1949,40 +1949,52 @@ pub(crate) fn clean_field_with_def_id(
}

pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
let discriminant = match variant.discr {
ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
ty::VariantDiscr::Relative(_) => None,
};

let kind = match variant.ctor_kind() {
Some(CtorKind::Const) => Variant::CLike(match variant.discr {
ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
ty::VariantDiscr::Relative(_) => None,
}),
Some(CtorKind::Fn) => Variant::Tuple(
Some(CtorKind::Const) => VariantKind::CLike,
Some(CtorKind::Fn) => VariantKind::Tuple(
variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
),
None => Variant::Struct(VariantStruct {
None => VariantKind::Struct(VariantStruct {
ctor_kind: None,
fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
}),
};
Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx)

Item::from_def_id_and_parts(
variant.def_id,
Some(variant.name),
VariantItem(Variant { kind, discriminant }),
cx,
)
}

fn clean_variant_data<'tcx>(
variant: &hir::VariantData<'tcx>,
disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
match variant {
hir::VariantData::Struct(..) => Variant::Struct(VariantStruct {
let discriminant = disr_expr.map(|disr| Discriminant {
expr: Some(disr.body),
value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
});

let kind = match variant {
hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct {
ctor_kind: None,
fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
hir::VariantData::Tuple(..) => {
Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
VariantKind::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
}
hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
expr: Some(disr.body),
value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
})),
}
hir::VariantData::Unit(..) => VariantKind::CLike,
};

Variant { discriminant, kind }
}

fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
Expand Down
24 changes: 16 additions & 8 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,11 @@ impl ItemKind {
match self {
StructItem(s) => s.fields.iter(),
UnionItem(u) => u.fields.iter(),
VariantItem(Variant::Struct(v)) => v.fields.iter(),
VariantItem(Variant::Tuple(v)) => v.iter(),
VariantItem(v) => match &v.kind {
VariantKind::CLike => [].iter(),
VariantKind::Tuple(t) => t.iter(),
VariantKind::Struct(s) => s.fields.iter(),
},
EnumItem(e) => e.variants.iter(),
TraitItem(t) => t.items.iter(),
ImplItem(i) => i.items.iter(),
Expand All @@ -824,7 +827,6 @@ impl ItemKind {
| TyMethodItem(_)
| MethodItem(_, _)
| StructFieldItem(_)
| VariantItem(_)
| ForeignFunctionItem(_)
| ForeignStaticItem(_)
| ForeignTypeItem
Expand Down Expand Up @@ -2136,17 +2138,23 @@ impl Enum {
}

#[derive(Clone, Debug)]
pub(crate) enum Variant {
CLike(Option<Discriminant>),
pub(crate) struct Variant {
pub kind: VariantKind,
pub discriminant: Option<Discriminant>,
}

#[derive(Clone, Debug)]
pub(crate) enum VariantKind {
CLike,
Tuple(Vec<Item>),
Struct(VariantStruct),
}

impl Variant {
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
match *self {
Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
Self::CLike(..) | Self::Tuple(_) => None,
match &self.kind {
VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()),
VariantKind::CLike | VariantKind::Tuple(_) => None,
}
}
}
Expand Down
26 changes: 15 additions & 11 deletions src/librustdoc/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,21 @@ pub(crate) trait DocFolder: Sized {
i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
ImplItem(i)
}
VariantItem(i) => match i {
Variant::Struct(mut j) => {
j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantItem(Variant::Struct(j))
}
Variant::Tuple(fields) => {
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantItem(Variant::Tuple(fields))
}
Variant::CLike(disr) => VariantItem(Variant::CLike(disr)),
},
VariantItem(Variant { kind, discriminant }) => {
let kind = match kind {
VariantKind::Struct(mut j) => {
j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantKind::Struct(j)
}
VariantKind::Tuple(fields) => {
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantKind::Tuple(fields)
}
VariantKind::CLike => VariantKind::CLike,
};

VariantItem(Variant { kind, discriminant })
}
ExternCrateItem { src: _ }
| ImportItem(_)
| FunctionItem(_)
Expand Down
37 changes: 20 additions & 17 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,15 +1220,15 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
w.write_str(" ");
let name = v.name.unwrap();
match *v.kind {
clean::VariantItem(ref var) => match var {
// FIXME(#101337): Show discriminant
clean::Variant::CLike(..) => write!(w, "{}", name),
clean::Variant::Tuple(ref s) => {
// FIXME(#101337): Show discriminant
clean::VariantItem(ref var) => match var.kind {
clean::VariantKind::CLike => write!(w, "{}", name),
clean::VariantKind::Tuple(ref s) => {
write!(w, "{}(", name);
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
clean::Variant::Struct(ref s) => {
clean::VariantKind::Struct(ref s) => {
render_struct(
w,
v,
Expand Down Expand Up @@ -1286,25 +1286,28 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
" rightside",
);
write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap());
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {

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

if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
w.write_str("(");
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
w.write_str("</h3></section>");

use crate::clean::Variant;

let heading_and_fields = match &*variant.kind {
clean::VariantItem(Variant::Struct(s)) => Some(("Fields", &s.fields)),
// Documentation on tuple variant fields is rare, so to reduce noise we only emit
// the section if at least one field is documented.
clean::VariantItem(Variant::Tuple(fields))
if fields.iter().any(|f| f.doc_value().is_some()) =>
{
Some(("Tuple Fields", fields))
let heading_and_fields = match &variant_data.kind {
clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)),
clean::VariantKind::Tuple(fields) => {
// Documentation on tuple variant fields is rare, so to reduce noise we only emit
// the section if at least one field is documented.
if fields.iter().any(|f| f.doc_value().is_some()) {
Some(("Tuple Fields", fields))
} else {
None
}
}
_ => None,
clean::VariantKind::CLike => None,
};

if let Some((heading, fields)) = heading_and_fields {
Expand Down
17 changes: 11 additions & 6 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,15 +646,20 @@ impl FromWithTcx<clean::Enum> for Enum {

impl FromWithTcx<clean::Variant> for Variant {
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
use clean::Variant::*;
match variant {
CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))),
Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)),
Struct(s) => Variant::Struct {
use clean::VariantKind::*;

let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx));

let kind = match variant.kind {
CLike => VariantKind::Plain,
Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)),
Struct(s) => VariantKind::Struct {
fields_stripped: s.has_stripped_entries(),
fields: ids(s.fields, tcx),
},
}
};

Variant { kind, discriminant }
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/passes/stripper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
// implementations of traits are always public.
clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
// Variant fields have inherited visibility
clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true,
clean::VariantItem(clean::Variant {
kind: clean::VariantKind::Struct(..) | clean::VariantKind::Tuple(..),
..
}) => true,
_ => false,
};

Expand Down
8 changes: 4 additions & 4 deletions src/librustdoc/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ pub(crate) trait DocVisitor: Sized {
EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
VariantItem(i) => match i {
Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
Variant::CLike(_) => {}
VariantItem(i) => match &i.kind {
VariantKind::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
VariantKind::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
VariantKind::CLike => {}
},
ExternCrateItem { src: _ }
| ImportItem(_)
Expand Down
17 changes: 12 additions & 5 deletions src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};

/// rustdoc format-version.
pub const FORMAT_VERSION: u32 = 23;
pub const FORMAT_VERSION: u32 = 24;

/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
Expand Down Expand Up @@ -333,19 +333,26 @@ pub struct Enum {
pub impls: Vec<Id>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Variant {
/// Whether the variant is plain, a tuple-like, or struct-like. Contains the fields.
pub kind: VariantKind,
/// The discriminant, if explicitly specified.
pub discriminant: Option<Discriminant>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "variant_kind", content = "variant_inner")]
pub enum Variant {
/// A variant with no parentheses, and possible discriminant.
pub enum VariantKind {
/// A variant with no parentheses
///
/// ```rust
/// enum Demo {
/// PlainVariant,
/// PlainWithDiscriminant = 1,
/// }
/// ```
Plain(Option<Discriminant>),
Plain,
/// A variant with unnamed fields.
///
/// Unlike most of json, `#[doc(hidden)]` fields will be given as `None`
Expand Down
12 changes: 6 additions & 6 deletions src/test/rustdoc-json/enums/discriminant/basic.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#[repr(i8)]
pub enum Ordering {
// @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"'
// @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"'
// @is "$.index[*][?(@.name=='Less')].inner.discriminant.expr" '"-1"'
// @is "$.index[*][?(@.name=='Less')].inner.discriminant.value" '"-1"'
Less = -1,
// @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"'
// @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"'
// @is "$.index[*][?(@.name=='Equal')].inner.discriminant.expr" '"0"'
// @is "$.index[*][?(@.name=='Equal')].inner.discriminant.value" '"0"'
Equal = 0,
// @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"'
// @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"'
// @is "$.index[*][?(@.name=='Greater')].inner.discriminant.expr" '"1"'
// @is "$.index[*][?(@.name=='Greater')].inner.discriminant.value" '"1"'
Greater = 1,
}
36 changes: 18 additions & 18 deletions src/test/rustdoc-json/enums/discriminant/expr.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
pub enum Foo {
// @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"'
// @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"'
// @is "$.index[*][?(@.name=='Addition')].inner.discriminant.value" '"0"'
// @is "$.index[*][?(@.name=='Addition')].inner.discriminant.expr" '"{ _ }"'
Addition = 0 + 0,
// @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"'
// @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"'
// @is "$.index[*][?(@.name=='Bin')].inner.discriminant.value" '"1"'
// @is "$.index[*][?(@.name=='Bin')].inner.discriminant.expr" '"0b1"'
Bin = 0b1,
// @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"'
// @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"'
// @is "$.index[*][?(@.name=='Oct')].inner.discriminant.value" '"2"'
// @is "$.index[*][?(@.name=='Oct')].inner.discriminant.expr" '"0o2"'
Oct = 0o2,
// @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"'
// @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"'
// @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.value" '"3"'
// @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.expr" '"THREE"'
PubConst = THREE,
// @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"'
// @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"'
// @is "$.index[*][?(@.name=='Hex')].inner.discriminant.value" '"4"'
// @is "$.index[*][?(@.name=='Hex')].inner.discriminant.expr" '"0x4"'
Hex = 0x4,
// @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"'
// @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"'
// @is "$.index[*][?(@.name=='Cast')].inner.discriminant.value" '"5"'
// @is "$.index[*][?(@.name=='Cast')].inner.discriminant.expr" '"{ _ }"'
Cast = 5 as isize,
// @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"'
// @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"'
// @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.value" '"6"'
// @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.expr" '"{ _ }"'
PubCall = six(),
// @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"'
// @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"'
// @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.value" '"7"'
// @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.expr" '"{ _ }"'
PrivCall = seven(),
// @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"'
// @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"'
// @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.value" '"8"'
// @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.expr" '"EIGHT"'
PrivConst = EIGHT,
}

Expand Down
Loading

0 comments on commit 0d5c5fa

Please sign in to comment.