Change:
At some point their should also be a for , and probably a way to tell what position each of the non stripped items are, as currently each of these 3 variants are documented with the same inner. but HTML gets a good representation:  The solution is probably to do what we do for structs, and store the , and a , such that each field of a varient gets an to hold the . We also should have a numfields, as even in that schema, you can't tell the difference between This also effects struct AFAIKT. I don't think this needs to be done now. I'll file an issue for it. Originally posted by in modify labels: +A-rustdoc-json +T-rustdoc
Related:

Discussion:
) - visited elif item["kind"] == "variant": if item["inner"]["variant_kind"] == "tuple": <del> for ty in item["inner"]["variant_inner"]: check_type(ty) </del> <ins> for field_id in filter(None, item["inner"]["variant_inner"]): work_list.add(field_id) </ins> elif item["inner"]["variant_kind"] == "struct": <del> work_list |= set(item["inner"]["variant_inner"]) - visited </del> <ins> work_list |= set(item["inner"]["variant_inner"]["fields"]) - visited </ins> elif item["kind"] in ("function", "method"): check_generics(item["inner"]["generics"]) check_decl(item["inner"]["decl"])

use clean::Variant::*; match variant { CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))), <del> Tuple(fields) => Variant::Tuple( fields .into_iter() .filter_map(|f| match *f.kind { clean::StructFieldItem(ty) => Some(ty.into_tcx(tcx)), clean::StrippedItem(_) => None, _ => unreachable!(), }) .collect(), ), Struct(s) => Variant::Struct(ids(s.fields, tcx)), </del> <ins> Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)), Struct(s) => Variant::Struct { fields_stripped: s.has_stripped_entries(), fields: ids(s.fields, tcx), }, </ins> } } }

.map(|i| from_item_id_with_name(i.item_id, tcx, i.name)) .collect() } <ins> fn ids_keeping_stripped( items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>, ) -> Vec<Option<Id>> { items .into_iter() .map(|i| { if !i.is_stripped() && !i.is_keyword() { Some(from_item_id_with_name(i.item_id, tcx, i.name)) } else { None } }) .collect() } </ins>

use serde::{Deserialize, Serialize}; /// rustdoc format-version. <del> pub const FORMAT_VERSION: u32 = 19; </del> <ins> pub const FORMAT_VERSION: u32 = 20; </ins> /// 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

#[serde(rename_all = "snake_case")] #[serde(tag = "variant_kind", content = "variant_inner")] pub enum Variant { <ins> /// A variant with no parentheses, and possible discriminant. /// /// ```rust /// enum Demo { ///     PlainVariant, ///     PlainWithDiscriminant = 1, /// } /// ``` </ins> Plain(Option<Discriminant>), <del> Tuple(Vec<Type>), Struct(Vec<Id>), </del> <ins> /// A variant with unnamed fields. /// /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None` /// instead of being ommited, because order matters. /// /// ```rust /// enum Demo { ///     TupleVariant(i32), ///     EmptyTupleVariant(), /// } /// ``` Tuple(Vec<Option<Id>>), /// A variant with named fields. /// /// ```rust /// enum Demo { ///     StructVariant { x: i32 }, ///     EmptyStructVariant {}, /// } /// ``` Struct { fields: Vec<Id>, fields_stripped: bool }, </ins> } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]

<del> // Regression test for <https://github.com/rust-lang/rust/issues/100529>. #![no_core] #![feature(no_core)] // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), } </del>

<ins> // Regression test for <https://github.com/rust-lang/rust/issues/100529>. #![no_core] #![feature(no_core)] // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [null] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), } </ins>

<ins> // ignore-tidy-linelength #![feature(no_core)] #![no_core] pub enum Foo { // @set Unit = "$.index[*][?(@.name=='Unit')].id" // @is "$.index[*][?(@.name=='Unit')].inner.variant_kind" '"plain"' // @is "$.index[*][?(@.name=='Unit')].inner.variant_inner" null Unit, // @set Named = "$.index[*][?(@.name=='Named')].id" // @is "$.index[*][?(@.name=='Named')].inner.variant_kind" '"struct"' // @is "$.index[*][?(@.name=='Named')].inner.variant_inner" '{"fields": [], "fields_stripped": false}' Named {}, // @set Tuple = "$.index[*][?(@.name=='Tuple')].id" // @is "$.index[*][?(@.name=='Tuple')].inner.variant_kind" '"tuple"' // @is "$.index[*][?(@.name=='Tuple')].inner.variant_inner" [] Tuple(), // @set NamedField = "$.index[*][?(@.name=='NamedField')].id" // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id" // @is "$.index[*][?(@.name=='NamedField')].inner.variant_kind" '"struct"' // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields[*]" $x // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields_stripped" false NamedField { x: i32 }, // @set TupleField = "$.index[*][?(@.name=='TupleField')].id" // @is "$.index[*][?(@.name=='TupleField')].inner.variant_kind" '"tuple"' // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id" // @is "$.index[*][?(@.name=='TupleField')].inner.variant_inner[*]" $tup_field TupleField(i32), } // @is    "$.index[*][?(@.name=='Foo')].inner.variants[0]" $Unit // @is    "$.index[*][?(@.name=='Foo')].inner.variants[1]" $Named // @is    "$.index[*][?(@.name=='Foo')].inner.variants[2]" $Tuple // @is    "$.index[*][?(@.name=='Foo')].inner.variants[3]" $NamedField // @is    "$.index[*][?(@.name=='Foo')].inner.variants[4]" $TupleField // @count "$.index[*][?(@.name=='Foo')].inner.variants[*]" 5 </ins>

<ins> pub enum Foo { Variant { #[doc(hidden)] a: i32, // @set b = "$.index[*][?(@.name=='b')].id" b: i32, #[doc(hidden)] x: i32, // @set y = "$.index[*][?(@.name=='y')].id" y: i32, }, // @is "$.index[*][?(@.name=='Variant')].inner.variant_kind" '"struct"' // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields_stripped" true // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[0]" $b // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[1]" $y // @count "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[*]" 2 } </ins>

<ins> #![feature(no_core)] #![no_core] // @set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id" // @set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id" // @set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id" // @set 2.2.1 = "$.index[*][?(@.docs=='2.2.1')].id" // @set 2.3.0 = "$.index[*][?(@.docs=='2.3.0')].id" // @set 3.1.1 = "$.index[*][?(@.docs=='3.1.1')].id" // @set 3.1.2 = "$.index[*][?(@.docs=='3.1.2')].id" // @set 3.2.0 = "$.index[*][?(@.docs=='3.2.0')].id" // @set 3.2.2 = "$.index[*][?(@.docs=='3.2.2')].id" // @set 3.3.0 = "$.index[*][?(@.docs=='3.3.0')].id" // @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id" pub enum EnumWithStrippedTupleVariants { // @is    "$.index[*][?(@.name=='None')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='None')].inner.variant_inner[*]" 0 None(), // @is    "$.index[*][?(@.name=='One')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='One')].inner.variant_inner[*]" 1 // @is    "$.index[*][?(@.name=='One')].inner.variant_inner[0]" $1.1.0 One(/** 1.1.0*/ bool), // @is    "$.index[*][?(@.name=='OneHidden')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[*]" 1 // @is    "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[0]" null OneHidden(#[doc(hidden)] bool), // @is    "$.index[*][?(@.name=='Two')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='Two')].inner.variant_inner[*]" 2 // @is    "$.index[*][?(@.name=='Two')].inner.variant_inner[0]" $2.1.0 // @is    "$.index[*][?(@.name=='Two')].inner.variant_inner[1]" $2.1.1 Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool), // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[*]" 2 // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[0]" null // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[1]" $2.2.1 TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool), // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[*]" 2 // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[0]" $2.3.0 // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[1]" null TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool), // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[*]" 2 // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[0]" null // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[1]" null TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool), // @is    "$.index[*][?(@.name=='Three1')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='Three1')].inner.variant_inner[*]" 3 // @is    "$.index[*][?(@.name=='Three1')].inner.variant_inner[0]" null // @is    "$.index[*][?(@.name=='Three1')].inner.variant_inner[1]" $3.1.1 // @is    "$.index[*][?(@.name=='Three1')].inner.variant_inner[2]" $3.1.2 Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool), // @is    "$.index[*][?(@.name=='Three2')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='Three2')].inner.variant_inner[*]" 3 // @is    "$.index[*][?(@.name=='Three2')].inner.variant_inner[0]" $3.2.0 // @is    "$.index[*][?(@.name=='Three2')].inner.variant_inner[1]" null // @is    "$.index[*][?(@.name=='Three2')].inner.variant_inner[2]" $3.2.2 Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool), // @is    "$.index[*][?(@.name=='Three3')].inner.variant_kind" '"tuple"' // @count "$.index[*][?(@.name=='Three3')].inner.variant_inner[*]" 3 // @is    "$.index[*][?(@.name=='Three3')].inner.variant_inner[0]" $3.3.0 // @is    "$.index[*][?(@.name=='Three3')].inner.variant_inner[1]" $3.3.1 // @is    "$.index[*][?(@.name=='Three3')].inner.variant_inner[2]" null Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool), } // @is "$.index[*][?(@.docs=='1.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.1')].name" '"1"' // @is "$.index[*][?(@.docs=='2.2.1')].name" '"1"' // @is "$.index[*][?(@.docs=='2.3.0')].name" '"0"' // @is "$.index[*][?(@.docs=='3.1.1')].name" '"1"' // @is "$.index[*][?(@.docs=='3.1.2')].name" '"2"' // @is "$.index[*][?(@.docs=='3.2.0')].name" '"0"' // @is "$.index[*][?(@.docs=='3.2.2')].name" '"2"' // @is "$.index[*][?(@.docs=='3.3.0')].name" '"0"' // @is "$.index[*][?(@.docs=='3.3.1')].name" '"1"' // @is "$.index[*][?(@.docs=='1.1.0')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='2.1.0')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='2.1.1')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='2.2.1')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='2.3.0')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.1.1')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.1.2')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.2.0')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.2.2')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.3.0')].inner" '{"kind": "primitive", "inner": "bool"}' // @is "$.index[*][?(@.docs=='3.3.1')].inner" '{"kind": "primitive", "inner": "bool"}' </ins>