about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNixon Enraght-Moony <nixon.emoony@gmail.com>2022-09-07 09:37:22 +0100
committerNixon Enraght-Moony <nixon.emoony@gmail.com>2022-09-07 09:42:23 +0100
commit1c8de173238a02abeb5642c25c3cef1eea52ac18 (patch)
tree12f2484c759eea2db34c0fdacfba2c1503060458
parent78a891d364a7358ed9eb9c93099ba2f3e6817ca6 (diff)
downloadrust-1c8de173238a02abeb5642c25c3cef1eea52ac18.tar.gz
rust-1c8de173238a02abeb5642c25c3cef1eea52ac18.zip
Rustdoc-Json: More accurate struct type.
Closes #101489
-rw-r--r--src/etc/check_missing_items.py8
-rw-r--r--src/librustdoc/json/conversions.rs36
-rw-r--r--src/rustdoc-json-types/lib.rs42
-rw-r--r--src/rustdoc-json-types/tests.rs4
-rw-r--r--src/test/rustdoc-json/nested.rs2
-rw-r--r--src/test/rustdoc-json/structs/plain_all_pub.rs11
-rw-r--r--src/test/rustdoc-json/structs/plain_doc_hidden.rs11
-rw-r--r--src/test/rustdoc-json/structs/plain_empty.rs9
-rw-r--r--src/test/rustdoc-json/structs/plain_pub_priv.rs9
-rw-r--r--src/test/rustdoc-json/structs/tuple.rs7
-rw-r--r--src/test/rustdoc-json/structs/tuple_empty.rs2
-rw-r--r--src/test/rustdoc-json/structs/tuple_pub_priv.rs13
-rw-r--r--src/test/rustdoc-json/structs/unit.rs7
-rw-r--r--src/test/rustdoc-json/structs/with_generics.rs16
-rw-r--r--src/test/rustdoc-json/structs/with_primitives.rs12
15 files changed, 118 insertions, 71 deletions
diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py
index 27fb018aeca..991c881bae1 100644
--- a/src/etc/check_missing_items.py
+++ b/src/etc/check_missing_items.py
@@ -132,9 +132,11 @@ while work_list:
         work_list |= set(item["inner"]["items"]) - visited
     elif item["kind"] == "struct":
         check_generics(item["inner"]["generics"])
-        work_list |= (
-            set(item["inner"]["fields"]) | set(item["inner"]["impls"])
-        ) - visited
+        work_list |= set(item["inner"]["impls"]) - visited
+        if "tuple" in item["inner"]["kind"]:
+            work_list |= set(filter(None, item["inner"]["kind"]["tuple"])) - visited
+        elif "plain" in item["inner"]["kind"]:
+            work_list |= set(item["inner"]["kind"]["plain"]["fields"]) - visited
     elif item["kind"] == "struct_field":
         check_type(item["inner"])
     elif item["kind"] == "enum":
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index c2d3543942d..1177d482ac0 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -304,11 +304,19 @@ impl FromWithTcx<clean::Struct> for Struct {
     fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
         let fields_stripped = struct_.has_stripped_entries();
         let clean::Struct { struct_type, generics, fields } = struct_;
+
+        let kind = match struct_type {
+            CtorKind::Fn => StructKind::Tuple(ids_keeping_stripped(fields, tcx)),
+            CtorKind::Const => {
+                assert!(fields.is_empty());
+                StructKind::Unit
+            }
+            CtorKind::Fictive => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
+        };
+
         Struct {
-            struct_type: from_ctor_kind(struct_type),
+            kind,
             generics: generics.into_tcx(tcx),
-            fields_stripped,
-            fields: ids(fields, tcx),
             impls: Vec::new(), // Added in JsonRenderer::item
         }
     }
@@ -327,14 +335,6 @@ impl FromWithTcx<clean::Union> for Union {
     }
 }
 
-pub(crate) fn from_ctor_kind(struct_type: CtorKind) -> StructType {
-    match struct_type {
-        CtorKind::Fictive => StructType::Plain,
-        CtorKind::Fn => StructType::Tuple,
-        CtorKind::Const => StructType::Unit,
-    }
-}
-
 pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
     Header {
         async_: header.is_async(),
@@ -644,20 +644,6 @@ impl FromWithTcx<clean::Enum> for Enum {
     }
 }
 
-impl FromWithTcx<clean::VariantStruct> for Struct {
-    fn from_tcx(struct_: clean::VariantStruct, tcx: TyCtxt<'_>) -> Self {
-        let fields_stripped = struct_.has_stripped_entries();
-        let clean::VariantStruct { struct_type, fields } = struct_;
-        Struct {
-            struct_type: from_ctor_kind(struct_type),
-            generics: Generics { params: vec![], where_predicates: vec![] },
-            fields_stripped,
-            fields: ids(fields, tcx),
-            impls: Vec::new(),
-        }
-    }
-}
-
 impl FromWithTcx<clean::Variant> for Variant {
     fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
         use clean::Variant::*;
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index eea62f3af5a..13bafa506e4 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -9,7 +9,7 @@ use std::path::PathBuf;
 use serde::{Deserialize, Serialize};
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 20;
+pub const FORMAT_VERSION: u32 = 21;
 
 /// 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
@@ -289,14 +289,40 @@ pub struct Union {
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Struct {
-    pub struct_type: StructType,
+    pub kind: StructKind,
     pub generics: Generics,
-    pub fields_stripped: bool,
-    pub fields: Vec<Id>,
     pub impls: Vec<Id>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum StructKind {
+    /// A struct with no fields and no parentheses.
+    ///
+    /// ```rust
+    /// pub struct Unit;
+    /// ```
+    Unit,
+    /// A struct with unnamed fields.
+    ///
+    /// ```rust
+    /// pub struct TupleStruct(i32);
+    /// pub struct EmptyTupleStruct();
+    /// ```
+    ///
+    /// All [`Id`]'s will point to [`ItemEnum::StructField`]. Private and
+    /// `#[doc(hidden)]` fields will be given as `None`
+    Tuple(Vec<Option<Id>>),
+    /// A struct with nammed fields.
+    ///
+    /// ```rust
+    /// pub struct PlainStruct { x: i32 }
+    /// pub struct EmptyPlainStruct {}
+    /// ```
+    Plain { fields: Vec<Id>, fields_stripped: bool },
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Enum {
     pub generics: Generics,
     pub variants_stripped: bool,
@@ -358,14 +384,6 @@ pub struct Discriminant {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub enum StructType {
-    Plain,
-    Tuple,
-    Unit,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Header {
     #[serde(rename = "const")]
     pub const_: bool,
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index e7f6447ed87..399ff54b294 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -3,10 +3,8 @@ use super::*;
 #[test]
 fn test_struct_info_roundtrip() {
     let s = ItemEnum::Struct(Struct {
-        struct_type: StructType::Plain,
         generics: Generics { params: vec![], where_predicates: vec![] },
-        fields_stripped: false,
-        fields: vec![],
+        kind: StructKind::Plain { fields: vec![], fields_stripped: false },
         impls: vec![],
     });
 
diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs
index 73ec9392ce9..ee2d2efa960 100644
--- a/src/test/rustdoc-json/nested.rs
+++ b/src/test/rustdoc-json/nested.rs
@@ -17,7 +17,7 @@ pub mod l1 {
     pub mod l3 {
 
         // @is "$.index[*][?(@.name=='L4')].kind" \"struct\"
-        // @is "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
+        // @is "$.index[*][?(@.name=='L4')].inner.kind" \"unit\"
         // @set l4_id = "$.index[*][?(@.name=='L4')].id"
         // @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
         pub struct L4;
diff --git a/src/test/rustdoc-json/structs/plain_all_pub.rs b/src/test/rustdoc-json/structs/plain_all_pub.rs
new file mode 100644
index 00000000000..b86ab93c264
--- /dev/null
+++ b/src/test/rustdoc-json/structs/plain_all_pub.rs
@@ -0,0 +1,11 @@
+pub struct Demo {
+    pub x: i32,
+    pub y: i32,
+}
+
+// @set x = "$.index[*][?(@.name=='x')].id"
+// @set y = "$.index[*][?(@.name=='y')].id"
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[1]" $y
+// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 2
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" false
diff --git a/src/test/rustdoc-json/structs/plain_doc_hidden.rs b/src/test/rustdoc-json/structs/plain_doc_hidden.rs
new file mode 100644
index 00000000000..7800b55a481
--- /dev/null
+++ b/src/test/rustdoc-json/structs/plain_doc_hidden.rs
@@ -0,0 +1,11 @@
+pub struct Demo {
+    pub x: i32,
+    #[doc(hidden)]
+    pub y: i32,
+}
+
+// @set x = "$.index[*][?(@.name=='x')].id"
+// @!has "$.index[*][?(@.name=='y')].id"
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
diff --git a/src/test/rustdoc-json/structs/plain_empty.rs b/src/test/rustdoc-json/structs/plain_empty.rs
index 2ad9e86096c..1d01b8bc14a 100644
--- a/src/test/rustdoc-json/structs/plain_empty.rs
+++ b/src/test/rustdoc-json/structs/plain_empty.rs
@@ -1,6 +1,5 @@
-// @has "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
-// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\"
-// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false
-// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields" []
+// @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
+// @is "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields_stripped" false
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields" []
 pub struct PlainEmpty {}
diff --git a/src/test/rustdoc-json/structs/plain_pub_priv.rs b/src/test/rustdoc-json/structs/plain_pub_priv.rs
new file mode 100644
index 00000000000..9b771224d97
--- /dev/null
+++ b/src/test/rustdoc-json/structs/plain_pub_priv.rs
@@ -0,0 +1,9 @@
+pub struct Demo {
+    pub x: i32,
+    y: i32,
+}
+
+// @set x = "$.index[*][?(@.name=='x')].id"
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
diff --git a/src/test/rustdoc-json/structs/tuple.rs b/src/test/rustdoc-json/structs/tuple.rs
index 91fac359422..6bdb753ee01 100644
--- a/src/test/rustdoc-json/structs/tuple.rs
+++ b/src/test/rustdoc-json/structs/tuple.rs
@@ -1,5 +1,4 @@
-// @has "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
-// @has "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\"
-// @has "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true
+// @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
+// @is "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
+// @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" '[null, null]'
 pub struct Tuple(u32, String);
diff --git a/src/test/rustdoc-json/structs/tuple_empty.rs b/src/test/rustdoc-json/structs/tuple_empty.rs
new file mode 100644
index 00000000000..0ad6a89547f
--- /dev/null
+++ b/src/test/rustdoc-json/structs/tuple_empty.rs
@@ -0,0 +1,2 @@
+// @is "$.index[*][?(@.name=='TupleUnit')].inner.kind.tuple" []
+pub struct TupleUnit();
diff --git a/src/test/rustdoc-json/structs/tuple_pub_priv.rs b/src/test/rustdoc-json/structs/tuple_pub_priv.rs
new file mode 100644
index 00000000000..9d5a1d1c8be
--- /dev/null
+++ b/src/test/rustdoc-json/structs/tuple_pub_priv.rs
@@ -0,0 +1,13 @@
+pub struct Demo(
+    i32,
+    /// field
+    pub i32,
+    #[doc(hidden)] i32,
+);
+
+// @set field = "$.index[*][?(@.docs=='field')].id"
+
+// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[0]" null
+// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[1]" $field
+// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[2]" null
+// @count "$.index[*][?(@.name=='Demo')].inner.kind.tuple[*]" 3
diff --git a/src/test/rustdoc-json/structs/unit.rs b/src/test/rustdoc-json/structs/unit.rs
index 85a515b5e78..26570971721 100644
--- a/src/test/rustdoc-json/structs/unit.rs
+++ b/src/test/rustdoc-json/structs/unit.rs
@@ -1,5 +1,4 @@
-// @has "$.index[*][?(@.name=='Unit')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Unit')].kind" \"struct\"
-// @has "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\"
-// @has "$.index[*][?(@.name=='Unit')].inner.fields" []
+// @is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
+// @is "$.index[*][?(@.name=='Unit')].kind" \"struct\"
+// @is "$.index[*][?(@.name=='Unit')].inner.kind" \"unit\"
 pub struct Unit;
diff --git a/src/test/rustdoc-json/structs/with_generics.rs b/src/test/rustdoc-json/structs/with_generics.rs
index b0ad1883f8a..00474800a0e 100644
--- a/src/test/rustdoc-json/structs/with_generics.rs
+++ b/src/test/rustdoc-json/structs/with_generics.rs
@@ -1,13 +1,13 @@
 use std::collections::HashMap;
 
-// @has "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
+// @is "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields" []
 pub struct WithGenerics<T, U> {
     stuff: Vec<T>,
     things: HashMap<U, U>,
diff --git a/src/test/rustdoc-json/structs/with_primitives.rs b/src/test/rustdoc-json/structs/with_primitives.rs
index b74050dde78..9c5a37f3957 100644
--- a/src/test/rustdoc-json/structs/with_primitives.rs
+++ b/src/test/rustdoc-json/structs/with_primitives.rs
@@ -1,9 +1,9 @@
-// @has "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
-// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
-// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
-// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
-// @has "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
+// @is "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields" []
 pub struct WithPrimitives<'a> {
     num: u32,
     s: &'a str,