From ed30993456224998db3a8f347a286f8234cd75c8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Aug 2021 14:43:22 +0200 Subject: [PATCH 1/2] Use the correct type for Enum variant tuples --- src/librustdoc/clean/mod.rs | 26 ++++++++++----- src/librustdoc/clean/types.rs | 3 +- src/librustdoc/fold.rs | 4 +++ src/librustdoc/html/render/print_item.rs | 41 ++++++++++++++---------- src/librustdoc/json/conversions.rs | 13 +++++++- src/librustdoc/passes/stripper.rs | 4 +-- 6 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b6ff3890c584e..5b4a1a3d849b6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1703,12 +1703,28 @@ impl Clean for rustc_hir::VariantData<'_> { } } +impl Clean> for hir::VariantData<'_> { + fn clean(&self, cx: &mut DocContext<'_>) -> Vec { + self.fields().iter().map(|x| x.clean(cx)).collect() + } +} + impl Clean for ty::VariantDef { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let kind = match self.ctor_kind { CtorKind::Const => Variant::CLike, CtorKind::Fn => Variant::Tuple( - self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(), + self.fields + .iter() + .map(|field| { + let name = Some(field.ident.name); + let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx)); + let what_rustc_thinks = + Item::from_def_id_and_parts(field.did, name, kind, cx); + // don't show `pub` for fields, which are always public + Item { visibility: Visibility::Inherited, ..what_rustc_thinks } + }) + .collect(), ), CtorKind::Fictive => Variant::Struct(VariantStruct { struct_type: CtorKind::Fictive, @@ -1738,13 +1754,7 @@ impl Clean for hir::VariantData<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Variant { match self { hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)), - // Important note here: `Variant::Tuple` is used on tuple structs which are not in an - // enum (so where converting from `ty::VariantDef`). In case we are in an enum, the kind - // is provided by the `Variant` wrapper directly, and since we need the fields' name - // (even for a tuple struct variant!), it's simpler to just store it as a - // `Variant::Struct` instead of a `Variant::Tuple` (otherwise it would force us to make - // a lot of changes when rendering them to generate the name as well). - hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)), + hir::VariantData::Tuple(..) => Variant::Tuple(self.clean(cx)), hir::VariantData::Unit(..) => Variant::CLike, } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7025574914331..4194c99c0ba70 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -715,6 +715,7 @@ impl ItemKind { StructItem(s) => s.fields.iter(), UnionItem(u) => u.fields.iter(), VariantItem(Variant::Struct(v)) => v.fields.iter(), + VariantItem(Variant::Tuple(v)) => v.iter(), EnumItem(e) => e.variants.iter(), TraitItem(t) => t.items.iter(), ImplItem(i) => i.items.iter(), @@ -1937,7 +1938,7 @@ crate struct Enum { #[derive(Clone, Debug)] crate enum Variant { CLike, - Tuple(Vec), + Tuple(Vec), Struct(VariantStruct), } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 45aae71d2dc57..b4859e4c9c7fe 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -56,6 +56,10 @@ crate trait DocFolder: Sized { || j.fields.iter().any(|f| f.is_stripped()); VariantItem(Variant::Struct(j)) } + Variant::Tuple(fields) => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantItem(Variant::Tuple(fields)) + } _ => VariantItem(i2), } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 8f4857a693928..722cfc97a8d89 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -937,6 +937,19 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni document_type_layout(w, cx, def_id); } +fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) { + for (i, ty) in s + .iter() + .map(|f| if let clean::StructFieldItem(ref ty) = *f.kind { ty } else { unreachable!() }) + .enumerate() + { + if i > 0 { + w.write_str(", "); + } + write!(w, "{}", ty.print(cx)); + } +} + fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { wrap_into_docblock(w, |w| { wrap_item(w, "enum", |w| { @@ -964,14 +977,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum match *v.kind { clean::VariantItem(ref var) => match var { clean::Variant::CLike => write!(w, "{}", name), - clean::Variant::Tuple(ref tys) => { + clean::Variant::Tuple(ref s) => { write!(w, "{}(", name); - for (i, ty) in tys.iter().enumerate() { - if i > 0 { - w.write_str(", ") - } - write!(w, "{}", ty.print(cx)); - } + print_tuple_struct_fields(w, cx, s); w.write_str(")"); } clean::Variant::Struct(ref s) => { @@ -1024,14 +1032,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum id = id, name = variant.name.as_ref().unwrap() ); - if let clean::VariantItem(clean::Variant::Tuple(ref tys)) = *variant.kind { + if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind { w.write_str("("); - for (i, ty) in tys.iter().enumerate() { - if i > 0 { - w.write_str(", "); - } - write!(w, "{}", ty.print(cx)); - } + print_tuple_struct_fields(w, cx, s); w.write_str(")"); } w.write_str(""); @@ -1041,7 +1044,11 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum document_non_exhaustive(w, variant); use crate::clean::Variant; - if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind { + if let Some((extra, fields)) = match *variant.kind { + clean::VariantItem(Variant::Struct(ref s)) => Some(("", &s.fields)), + clean::VariantItem(Variant::Tuple(ref fields)) => Some(("Tuple ", fields)), + _ => None, + } { let variant_id = cx.derive_id(format!( "{}.{}.fields", ItemType::Variant, @@ -1051,10 +1058,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum write!( w, "

{extra}Fields of {name}

", - extra = if s.struct_type == CtorKind::Fn { "Tuple " } else { "" }, + extra = extra, name = variant.name.as_ref().unwrap(), ); - for field in &s.fields { + for field in fields { use crate::clean::StructFieldItem; if let StructFieldItem(ref ty) = *field.kind { let id = cx.derive_id(format!( diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f3eeea6c6ae0b..9453e6d35ee67 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -569,7 +569,18 @@ impl FromWithTcx for Variant { use clean::Variant::*; match variant { CLike => Variant::Plain, - Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()), + Tuple(fields) => Variant::Tuple( + fields + .into_iter() + .map(|f| { + if let clean::StructFieldItem(ty) = *f.kind { + ty.into_tcx(tcx) + } else { + unreachable!() + } + }) + .collect(), + ), Struct(s) => Variant::Struct(ids(s.fields)), } } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 4305268c9aab0..a717c53d9d3f7 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -93,8 +93,8 @@ impl<'a> DocFolder for Stripper<'a> { // implementations of traits are always public. clean::ImplItem(ref imp) if imp.trait_.is_some() => true, - // Struct variant fields have inherited visibility - clean::VariantItem(clean::Variant::Struct(..)) => true, + // Variant fields have inherited visibility + clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true, _ => false, }; From a5213888e04b6bacda5198dc41026b604fe410ef Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Aug 2021 14:58:50 +0200 Subject: [PATCH 2/2] Add rustdonc-json tests for enum variants --- src/test/rustdoc-json/enums/variant_struct.rs | 11 +++++++++++ src/test/rustdoc-json/enums/variant_tuple_struct.rs | 6 ++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/rustdoc-json/enums/variant_struct.rs create mode 100644 src/test/rustdoc-json/enums/variant_tuple_struct.rs diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs new file mode 100644 index 0000000000000..246e6a09007b3 --- /dev/null +++ b/src/test/rustdoc-json/enums/variant_struct.rs @@ -0,0 +1,11 @@ +// @has variant_struct.json "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" +// @has - "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\" +pub enum EnumStruct { + // @has - "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\" + // @has - "$.index[*][?(@.name=='x')]" + // @has - "$.index[*][?(@.name=='y')]" + VariantS { + x: u32, + y: String, + }, +} diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs new file mode 100644 index 0000000000000..d948dc552cdbc --- /dev/null +++ b/src/test/rustdoc-json/enums/variant_tuple_struct.rs @@ -0,0 +1,6 @@ +// @has variant_tuple_struct.json "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" +// @has - "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\" +pub enum EnumTupleStruct { + // @has - "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\" + VariantA(u32, String), +}