Change:
I understand that if (at least one of) a tuple variant's fields is documented, we need a place to put that documentation. But if not this just adds superfluous noise. Especially if you have a lot of tuple enum variants with undocumented fields it becomes very noisy very quickly. As a real world example from one of my codebases: How it currently looks: ! And with the superfluous sections removed: ! I think we should get rid of any "Tuple Fields of Variant" section if that variants' fields are undocumented. It only adds noise and makes the documentation less readable in my opinion.
I wonder if instead we should just unconditionally get rid of the tuple fields in the header? Then it'd be consistent with struct fields. On the other hand, the header view is a bit easier to read in some ways since it matches source view. cc What do you think?
To clarify, you mean the heading of each variant, right? So e.g. SizeLimit(usize) would become SizeLimit, with a heading below that saying "Tuple Fields", and text below that saying ? I prefer an approach where we keep as the heading, and say "if none of the tuple fields has a doccomment (the common case), we don't show the "Tuple Fields" section (as suggested in the top comment). Perhaps we should even deprecate comments on individual tuple fields? It seems quite uncommon to use, and rather awkward.
I agree with proposition.
Yep, in general I think if the fields need documentation people will generally be using struct-variants instead, so optimizing for doc-less tuple-variants makes sense.
I disagree; we'd basically be removing expected behavior. I don't think we should force people to refactor their code just to add documentation. But optimizing for doc-less tuple variants (rather than enforcing it) seems potentially reasonable.
Thanks to I realized I misunderstood comment. So let me update my comment: I agree with this. I agree with this as well. I don't agree with this. Hopefully I didn't miss something else...
To clarify, you mean the heading of each variant, right? So e.g. SizeLimit(usize) would become SizeLimit, with a heading below that saying "Tuple Fields", and text below that saying 0: usize? I don't understand; you agree with both? The two approaches are mutually exclusive IIUC.
I don't have a preference is what I tried to say haha.
Since there's a PR up, I wanted to tidy up this issue thread. There was some confusion and back and forth above, but reading through it it seems like everyone who has chimed in either agrees with the original post's approach or doesn't have a preference. Since the PR () implements that approach, we're good.
I still think it's not great that now tuple fields and struct fields will be handled differently, but this seems like a good enough solution for now.

Discussion:
w.write_str("</h3>"); use crate::clean::Variant; <del> 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)), </del> <ins> let heading_and_fields = match &*variant.kind { clean::VariantItem(Variant::Struct(s)) => Some(("Fields", &s.fields)), // Documentation on tuple variant fields is rare, so to reduce noise we only emit // the section if at least one field is documented. clean::VariantItem(Variant::Tuple(fields)) if fields.iter().any(|f| f.doc_value().is_some()) => { Some(("Tuple Fields", fields)) } </ins> _ => None, <del> } { </del> <ins> }; if let Some((heading, fields)) = heading_and_fields { </ins> let variant_id = cx.derive_id(format!( "{}.{}.fields", ItemType::Variant, variant.name.as_ref().unwrap() )); write!(w, "<div class="sub-variant" id="{id}">", id = variant_id); <del> write!(w, "<h4>{extra}Fields</h4>", extra = extra,); </del> <ins> write!(w, "<h4>{heading}</h4>", heading = heading); </ins> document_non_exhaustive(w, variant); for field in fields { match *field.kind {

// @has - '//*[@id="variant.MixedHiddenFirst"]//code' 'MixedHiddenFirst(_, S)' // @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0 // @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S' <del> MixedHiddenFirst(#[doc(hidden)] H, S), </del> <ins> MixedHiddenFirst(#[doc(hidden)] H, /** dox */ S), </ins> // @has - '//*[@id="variant.MixedHiddenLast"]//code' 'MixedHiddenLast(S, _)' // @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S' // @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0 <del> MixedHiddenLast(S, #[doc(hidden)] H), </del> <ins> MixedHiddenLast(/** dox */ S, #[doc(hidden)] H), </ins> // @has - '//*[@id="variant.HiddenStruct"]//code' 'HiddenStruct' // @count - '//*[@id="variant.HiddenStruct.field.h"]' 0 // @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S' HiddenStruct { #[doc(hidden)] h: H, <ins> /// dox </ins> s: S, }, }

// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String' // @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs' // @matches - '//*[@id="variant.FooVariant.fields"]/h4' '^Fields$' <ins> // @has - '//*[@id="variant.BazVariant.fields"]//*[@class="docblock"]' 'dox' // @has - '//*[@id="variant.OtherVariant.fields"]//*[@class="docblock"]' 'dox' // @!matches - '//*[@id="variant.QuuxVariant.fields"]/h4' '^Tuple Fields$' </ins> pub enum Bar { BarVariant( /// Hello docs

/// hello x: u32, }, <ins> BazVariant( String, /// dox u32, ), OtherVariant( /// dox String, u32, ), QuuxVariant(String), </ins> }