diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1ccd6a2c0ef28..d820e43cb6123 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -236,7 +236,6 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum { clean::Enum { generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates), - variants_stripped: false, variants: cx.tcx.adt_def(did).variants().iter().map(|v| v.clean(cx)).collect(), } } @@ -249,7 +248,6 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct { struct_type: variant.ctor_kind, generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates), fields: variant.fields.iter().map(|x| x.clean(cx)).collect(), - fields_stripped: false, } } @@ -259,7 +257,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); let fields = variant.fields.iter().map(|x| x.clean(cx)).collect(); - clean::Union { generics, fields, fields_stripped: false } + clean::Union { generics, fields } } fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d5619bacf516..4ddfae4daccf8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1784,7 +1784,6 @@ impl Clean for rustc_hir::VariantData<'_> { VariantStruct { struct_type: CtorKind::from_hir(self), fields: self.fields().iter().map(|x| x.clean(cx)).collect(), - fields_stripped: false, } } } @@ -1804,7 +1803,6 @@ impl Clean for ty::VariantDef { } CtorKind::Fictive => Variant::Struct(VariantStruct { struct_type: CtorKind::Fictive, - fields_stripped: false, fields: self.fields.iter().map(|field| field.clean(cx)).collect(), }), }; @@ -1914,7 +1912,6 @@ fn clean_maybe_renamed_item( ItemKind::Enum(ref def, ref generics) => EnumItem(Enum { variants: def.variants.iter().map(|v| v.clean(cx)).collect(), generics: generics.clean(cx), - variants_stripped: false, }), ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias { generics: generics.clean(cx), @@ -1923,13 +1920,11 @@ fn clean_maybe_renamed_item( ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union { generics: generics.clean(cx), fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(), - fields_stripped: false, }), ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct { struct_type: CtorKind::from_hir(variant_data), generics: generics.clean(cx), fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(), - fields_stripped: false, }), ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx), // proc macros can have a name set by attributes diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1bb0219c42a3e..7118e05e58eb7 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -619,11 +619,12 @@ impl Item { _ => false, } } - pub(crate) fn has_stripped_fields(&self) -> Option { + pub(crate) fn has_stripped_entries(&self) -> Option { match *self.kind { - StructItem(ref _struct) => Some(_struct.fields_stripped), - UnionItem(ref union) => Some(union.fields_stripped), - VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped), + StructItem(ref struct_) => Some(struct_.has_stripped_entries()), + UnionItem(ref union_) => Some(union_.has_stripped_entries()), + EnumItem(ref enum_) => Some(enum_.has_stripped_entries()), + VariantItem(ref v) => v.has_stripped_entries(), _ => None, } } @@ -2028,14 +2029,24 @@ pub(crate) struct Struct { pub(crate) struct_type: CtorKind, pub(crate) generics: Generics, pub(crate) fields: Vec, - pub(crate) fields_stripped: bool, +} + +impl Struct { + pub(crate) fn has_stripped_entries(&self) -> bool { + self.fields.iter().any(|f| f.is_stripped()) + } } #[derive(Clone, Debug)] pub(crate) struct Union { pub(crate) generics: Generics, pub(crate) fields: Vec, - pub(crate) fields_stripped: bool, +} + +impl Union { + pub(crate) fn has_stripped_entries(&self) -> bool { + self.fields.iter().any(|f| f.is_stripped()) + } } /// This is a more limited form of the standard Struct, different in that @@ -2045,14 +2056,28 @@ pub(crate) struct Union { pub(crate) struct VariantStruct { pub(crate) struct_type: CtorKind, pub(crate) fields: Vec, - pub(crate) fields_stripped: bool, +} + +impl VariantStruct { + pub(crate) fn has_stripped_entries(&self) -> bool { + self.fields.iter().any(|f| f.is_stripped()) + } } #[derive(Clone, Debug)] pub(crate) struct Enum { pub(crate) variants: IndexVec, pub(crate) generics: Generics, - pub(crate) variants_stripped: bool, +} + +impl Enum { + pub(crate) fn has_stripped_entries(&self) -> bool { + self.variants.iter().any(|f| f.is_stripped()) + } + + pub(crate) fn variants(&self) -> impl Iterator { + self.variants.iter().filter(|v| !v.is_stripped()) + } } #[derive(Clone, Debug)] @@ -2062,6 +2087,15 @@ pub(crate) enum Variant { Struct(VariantStruct), } +impl Variant { + pub(crate) fn has_stripped_entries(&self) -> Option { + match *self { + Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()), + Self::CLike | Self::Tuple(_) => None, + } + } +} + /// Small wrapper around [`rustc_span::Span`] that adds helper methods /// and enforces calling [`rustc_span::Span::source_callsite()`]. #[derive(Copy, Clone, Debug)] diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index f3e075bc12a34..336448904d165 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -18,30 +18,15 @@ pub(crate) trait DocFolder: Sized { StrippedItem(..) => unreachable!(), ModuleItem(i) => ModuleItem(self.fold_mod(i)), StructItem(mut i) => { - let num_fields = i.fields.len(); i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - if !i.fields_stripped { - i.fields_stripped = - num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); - } StructItem(i) } UnionItem(mut i) => { - let num_fields = i.fields.len(); i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - if !i.fields_stripped { - i.fields_stripped = - num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped()); - } UnionItem(i) } EnumItem(mut i) => { - let num_variants = i.variants.len(); i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect(); - if !i.variants_stripped { - i.variants_stripped = num_variants != i.variants.len() - || i.variants.iter().any(|f| f.is_stripped()); - } EnumItem(i) } TraitItem(mut i) => { @@ -54,12 +39,7 @@ pub(crate) trait DocFolder: Sized { } VariantItem(i) => match i { Variant::Struct(mut j) => { - let num_fields = j.fields.len(); j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - if !j.fields_stripped { - j.fields_stripped = num_fields != j.fields.len() - || j.fields.iter().any(|f| f.is_stripped()); - } VariantItem(Variant::Struct(j)) } Variant::Tuple(fields) => { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 0de50c60facb3..1b4a2cf1cb0ac 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2363,8 +2363,7 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: let mut sidebar = Buffer::new(); let mut variants = e - .variants - .iter() + .variants() .filter_map(|v| { v.name .as_ref() diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 2c0b8d7bde146..ed41b95e73f09 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1136,6 +1136,7 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item] } fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { + let count_variants = e.variants().count(); wrap_into_docblock(w, |w| { wrap_item(w, "enum", |w| { render_attributes_in_pre(w, it, ""); @@ -1147,16 +1148,16 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum e.generics.print(cx), print_where_clause(&e.generics, cx, 0, true), ); - if e.variants.is_empty() && !e.variants_stripped { + let variants_stripped = e.has_stripped_entries(); + if count_variants == 0 && !variants_stripped { w.write_str(" {}"); } else { w.write_str(" {\n"); - let count_variants = e.variants.len(); let toggle = should_hide_fields(count_variants); if toggle { toggle_open(w, format_args!("{} variants", count_variants)); } - for v in &e.variants { + for v in e.variants() { w.write_str(" "); let name = v.name.unwrap(); match *v.kind { @@ -1185,7 +1186,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum w.write_str(",\n"); } - if e.variants_stripped { + if variants_stripped { w.write_str(" // some variants omitted\n"); } if toggle { @@ -1198,7 +1199,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum document(w, cx, it, None, HeadingOffset::H2); - if !e.variants.is_empty() { + if count_variants != 0 { write!( w, "

\ @@ -1206,7 +1207,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum document_non_exhaustive_header(it) ); document_non_exhaustive(w, it); - for variant in &e.variants { + for variant in e.variants() { let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( w, @@ -1650,7 +1651,7 @@ fn render_union( } } - if it.has_stripped_fields().unwrap() { + if it.has_stripped_entries().unwrap() { write!(w, " /* private fields */\n{}", tab); } if toggle { @@ -1706,11 +1707,11 @@ fn render_struct( } if has_visible_fields { - if it.has_stripped_fields().unwrap() { + if it.has_stripped_entries().unwrap() { write!(w, "\n{} /* private fields */", tab); } write!(w, "\n{}", tab); - } else if it.has_stripped_fields().unwrap() { + } else if it.has_stripped_entries().unwrap() { write!(w, " /* private fields */ "); } if toggle { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bc9920730dd3c..6a8e4787676e1 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -249,7 +249,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { impl FromWithTcx for Struct { fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { - let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_; + let fields_stripped = struct_.has_stripped_entries(); + let clean::Struct { struct_type, generics, fields } = struct_; Struct { struct_type: from_ctor_kind(struct_type), generics: generics.into_tcx(tcx), @@ -261,8 +262,9 @@ impl FromWithTcx for Struct { } impl FromWithTcx for Union { - fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self { - let clean::Union { generics, fields, fields_stripped } = struct_; + fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self { + let fields_stripped = union_.has_stripped_entries(); + let clean::Union { generics, fields } = union_; Union { generics: generics.into_tcx(tcx), fields_stripped, @@ -586,7 +588,8 @@ pub(crate) fn from_function_method( impl FromWithTcx for Enum { fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { - let clean::Enum { variants, generics, variants_stripped } = enum_; + let variants_stripped = enum_.has_stripped_entries(); + let clean::Enum { variants, generics } = enum_; Enum { generics: generics.into_tcx(tcx), variants_stripped, @@ -598,7 +601,8 @@ impl FromWithTcx for Enum { impl FromWithTcx for Struct { fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self { - let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_; + let fields_stripped = struct_.has_stripped_entries(); + let clean::VariantStruct { struct_type, fields } = struct_; Struct { struct_type: from_ctor_kind(struct_type), generics: Default::default(), diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index ab5526e0612b7..533e2ce46ddd8 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -38,9 +38,16 @@ impl<'a> DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if i.attrs.lists(sym::doc).has_word(sym::hidden) { debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); - // use a dedicated hidden item for given item type if any + // Use a dedicated hidden item for fields, variants, and modules. + // We need to keep private fields and variants, so that the docs + // can show a placeholder "// some variants omitted". We need to keep + // private modules, because they can contain impl blocks, and impl + // block privacy is inherited from the type and trait, not from the + // module it's defined in. Both of these are marked "stripped," and + // not included in the final docs, but since they still have an effect + // on the final doc, cannot be completely removed from the Clean IR. match *i.kind { - clean::StructFieldItem(..) | clean::ModuleItem(..) => { + clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { // We need to recurse into stripped modules to // strip things like impl methods but when doing so // we must not add any items to the `retained` set. diff --git a/src/test/rustdoc/strip-enum-variant.no-not-shown.html b/src/test/rustdoc/strip-enum-variant.no-not-shown.html new file mode 100644 index 0000000000000..c4ee1a9911436 --- /dev/null +++ b/src/test/rustdoc/strip-enum-variant.no-not-shown.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs index 12e576100710a..f82ffdfeda58f 100644 --- a/src/test/rustdoc/strip-enum-variant.rs +++ b/src/test/rustdoc/strip-enum-variant.rs @@ -2,6 +2,8 @@ // @has - '//code' 'Shown' // @!has - '//code' 'NotShown' // @has - '//code' '// some variants omitted' +// Also check that `NotShown` isn't displayed in the sidebar. +// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]/ul' pub enum MyThing { Shown, #[doc(hidden)]