diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index 025f320e3a1..27fb018aeca 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -144,10 +144,10 @@ while work_list: ) - visited elif item["kind"] == "variant": if item["inner"]["variant_kind"] == "tuple": - for ty in item["inner"]["variant_inner"]: - check_type(ty) + for field_id in filter(None, item["inner"]["variant_inner"]): + work_list.add(field_id) elif item["inner"]["variant_kind"] == "struct": - work_list |= set(item["inner"]["variant_inner"]) - visited + work_list |= set(item["inner"]["variant_inner"]["fields"]) - visited elif item["kind"] in ("function", "method"): check_generics(item["inner"]["generics"]) check_decl(item["inner"]["decl"]) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4d009316730..c2d3543942d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -663,17 +663,11 @@ 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( - 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)), + Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)), + Struct(s) => Variant::Struct { + fields_stripped: s.has_stripped_entries(), + fields: ids(s.fields, tcx), + }, } } } @@ -796,3 +790,19 @@ fn ids(items: impl IntoIterator, tcx: TyCtxt<'_>) -> Vec .map(|i| from_item_id_with_name(i.item_id, tcx, i.name)) .collect() } + +fn ids_keeping_stripped( + items: impl IntoIterator, + tcx: TyCtxt<'_>, +) -> Vec> { + 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() +} diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index d25f68b3743..eea62f3af5a 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 19; +pub const FORMAT_VERSION: u32 = 20; /// 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 @@ -308,9 +308,36 @@ pub struct Enum { #[serde(rename_all = "snake_case")] #[serde(tag = "variant_kind", content = "variant_inner")] pub enum Variant { + /// A variant with no parentheses, and possible discriminant. + /// + /// ```rust + /// enum Demo { + /// PlainVariant, + /// PlainWithDiscriminant = 1, + /// } + /// ``` Plain(Option), - Tuple(Vec), - Struct(Vec), + /// 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>), + /// A variant with named fields. + /// + /// ```rust + /// enum Demo { + /// StructVariant { x: i32 }, + /// EmptyStructVariant {}, + /// } + /// ``` + Struct { fields: Vec, fields_stripped: bool }, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/src/test/rustdoc-json/enum_variant_hidden.rs b/src/test/rustdoc-json/enums/field_hidden.rs similarity index 96% rename from src/test/rustdoc-json/enum_variant_hidden.rs rename to src/test/rustdoc-json/enums/field_hidden.rs index c5e063a055c..e6310cc3b99 100644 --- a/src/test/rustdoc-json/enum_variant_hidden.rs +++ b/src/test/rustdoc-json/enums/field_hidden.rs @@ -6,7 +6,7 @@ // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [null] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/src/test/rustdoc-json/enums/kind.rs b/src/test/rustdoc-json/enums/kind.rs new file mode 100644 index 00000000000..e9ea3ae23c2 --- /dev/null +++ b/src/test/rustdoc-json/enums/kind.rs @@ -0,0 +1,37 @@ +// 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 diff --git a/src/test/rustdoc-json/enums/struct_field_hidden.rs b/src/test/rustdoc-json/enums/struct_field_hidden.rs new file mode 100644 index 00000000000..f612a34a492 --- /dev/null +++ b/src/test/rustdoc-json/enums/struct_field_hidden.rs @@ -0,0 +1,17 @@ +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 +} diff --git a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs new file mode 100644 index 00000000000..f546eaa0d17 --- /dev/null +++ b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs @@ -0,0 +1,94 @@ +#![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"}'