rust icon indicating copy to clipboard operation
rust copied to clipboard

Tracking issue for `#[doc(cfg(…))]`, `#[doc(cfg_hide(…))]` and `doc_auto_cfg`

Open kennytm opened this issue 8 years ago • 95 comments

This is a tracking issue for the #[doc(cfg(…))] attribute (feature: doc_cfg) introduced in #43348 and #[doc(cfg_hide(…))] (feature: doc_cfg_hide) attribute introduced in #89596, along with the doc_auto_cfg feature introduced in https://github.com/rust-lang/rust/pull/90502.

Steps:

(cc #1998)

kennytm avatar Aug 10 '17 02:08 kennytm

#[cfg(rustdoc)] is also gated on this issue but seems distinct (and less risky). Could we FCP that portion in particular?

sfackler avatar Jan 07 '19 23:01 sfackler

I think that #[cfg(rustdoc)], when applied to structs, should automatically skip any non-public members. That would greatly reduce the amount of extra typing required by crates like Nix.

asomers avatar Jan 30 '19 17:01 asomers

I was just trying this out for documenting crate features, it "works" but if this is a potential usecase it would be nice to special case the rendering for it:


Screenshot 2019-07-04 at 12 35 06
Screenshot 2019-07-04 at 12 35 27

Nemo157 avatar Jul 04 '19 10:07 Nemo157

There is also the issue that it repeats every feature on every item in a page:

Screenshot 2019-07-04 at 14 17 45

When I last attempted to do something about rendering features I found it much more useful to separately keep track of "all required features" to render at the top of the items page and "newly introduced features" to render on the sub-items on the page, so you don't get this distracting repetition on every item.

Nemo157 avatar Jul 04 '19 12:07 Nemo157

We tried out this feature in Syn (https://github.com/dtolnay/syn/pull/734) and decided against using it yet.


What I am happy with

I like how the message turns out at the top of the doc page of a single type or function.

We had previously displayed this information using an italicized note, which was less noticeable.


What I am not happy with

Our index page becomes extremely noisy. I wish there were a way to not show all of these in our case. It is enough to have this information on the type's individual page. Cfg combinations are not among the most important information to show on the index page.

Also inheriting the same note onto every public field seems unnecessary in our use case.

dtolnay avatar Dec 25 '19 03:12 dtolnay

The links in the opening post have gone dead.

Lokathor avatar May 06 '20 16:05 Lokathor

What's the status of this? I've been using it on the time crate for as long as I can remember, and a number of other crates have been doing so as well.

jhpratt avatar Sep 24 '20 06:09 jhpratt

For searchability: this is feature doc_cfg.

Nemo157 avatar Oct 07 '20 21:10 Nemo157

I changed the rendering of feature="foo" cfgs in #75330, which vastly simplifies the display on module index pages like shown in the syn screenshot above. I have also just opened #77672 to address the other point @dtolnay had, that there is no need to repeat the exact same cfg rendering over and over when it is already implied by context.

Other than those changes, there are bugs around trait implementation handling such as #68100, I want to try and create an exhaustive test covering trait implementations once #77672 is done and fix their handling.

After that, I feel like this would be ready for stabilization, it's had quite thorough usage on docs.rs already, so when rendering is all fixed we can rebuild the documentation for some large crates like tokio that use it and check whether there's other edgecase bugs remaining.

Nemo157 avatar Oct 07 '20 21:10 Nemo157

I'm wondering: Would it not make sense to generate doc_cfg hints automatically for any #[cfg(...)] items, without also needing to type #[doc(cfg(...))]?

So the following

#[cfg(all(target_feature = "avx", target_feature = "avx2"))]
#[doc(cfg(all(target_feature = "avx", target_feature = "avx2")))]
pub mod avx;

could just be

#[cfg(all(target_feature = "avx", target_feature = "avx2"))]
pub mod avx;

Otherwise, we're duplicating information unnecessarily, right?

ArniDagur avatar Oct 07 '20 22:10 ArniDagur

...pretty much

Lokathor avatar Oct 07 '20 22:10 Lokathor

In the general case yes, but there are quite a few crates using things like internal cfg's generated by their build.rs for compiler version detection that would not want to show those cfg to their users.

Nemo157 avatar Oct 08 '20 07:10 Nemo157

What about the opposite - having #[doc(cfg(x))] also imply #[cfg(x)]? I can't imagine a scenario where you wouldn't want to have that.

jyn514 avatar Oct 15 '20 16:10 jyn514

Not sure how hard that would be to implement, though - maybe @petrochenkov would know?

jyn514 avatar Oct 15 '20 16:10 jyn514

I'm wondering: Would it not make sense to generate doc_cfg hints automatically for any #[cfg(...)] items, without also needing to type #[doc(cfg(...))]?

Issue with that is if you want to implement the same function on different platforms in different ways. It shouldn't show up as gated on the current platform, but as not gated at all... or if it's only implemented on a set of platforms, then as that list.

So if there is such an implication, it should be opt in, eg via an empty #[doc(cfg)] tag. Maybe one can have a feature to make it opt out for a region of code, or an entire crate, but that requires manual review of the code, so can't be the default.

having #[doc(cfg(x))] also imply #[cfg(x)]?

IMO it's strange if #[doc(...)] influences normal code.

est31 avatar Nov 20 '20 09:11 est31

This is mostly looking good for syn. Filed one bug regarding the rendering of doc cfg on impls of empty traits: #79279.

dtolnay avatar Nov 21 '20 21:11 dtolnay

One situation where it would be nice to have doc_cfg but doesn't currently seem to be feasible is on derive-generated implementations. Even if the provider of the derive wanted to, they'd have to manually accept an equivalent attribute to doc_cfg, only to pass it on.

Not something worth holding up stabilization over, but just something I noticed when adding in more attributes in some of my code.

jhpratt avatar Nov 23 '20 08:11 jhpratt

Can't we have something like a feature-selector, a ui for selecting which feature to show?

aobatact avatar Apr 02 '21 14:04 aobatact

I think https://github.com/rust-lang/rust/issues/84437 needs to be fixed before stabilizing this.

Can't we have something like a feature-selector, a ui for selecting which feature to show?

@aobatact the more features we add to doc(cfg), the longer it will be before it's stabilized. I would rather stabilize an MVP and then we can add features later.

jyn514 avatar Apr 22 '21 13:04 jyn514

There are some issues around how the #[doc(cfg)] annotations propagate from module to the items contained within, IIRC. It does only work in some circumstances (though I don't remember which ones, so I can't file a bug…)

That said, I don't think it or any other presentation concerns need to block the stabilization of the attribute itself – I don't believe the output of the rustdoc falls under the stability guarantees, so we can always fix that later.

nagisa avatar May 07 '21 12:05 nagisa

One situation where it would be nice to have doc_cfg but doesn't currently seem to be feasible is on derive-generated implementations. Even if the provider of the derive wanted to, they'd have to manually accept an equivalent attribute to doc_cfg, only to pass it on.

Do you want to show the cfg message on both the type and the impl? I'm having trouble understanding the use-case - when would that be necessary?

jyn514 avatar May 07 '21 13:05 jyn514

So you can put #[doc(cfg)] on a module and it will show up on the types within (or at least used to), but only in some cases – again I don't recall exactly what the circumstances were. This helps when you have #[doc(cfg(...))] #[cfg(any(docs, ...)] mod a_ton_of_optional_functionality; and want to avoid having to annotate with #[doc(cfg)] everything within the module, but you ultimately end up having to annotate everything anyway, because propagation is not working quite right.

nagisa avatar May 07 '21 14:05 nagisa

So you can put #[doc(cfg)] on a module and it will show up on the types within (or at least used to), but only in some cases – again I don't recall exactly what the circumstances were

This is unfortunately not super actionable, but please do open an issue if you can figure out how to replicate it!

jyn514 avatar May 07 '21 14:05 jyn514

I can only speak anecdotally, but I haven't run into any issues with this feature aside from the aforementioned derived traits behind a cfg gate (which shouldn't be a blocker imo).

jhpratt avatar May 07 '21 16:05 jhpratt

@jyn514 https://github.com/rust-lang/rust/issues/83428 is the same issue that I was hitting. As I said originally, though:

That said, I don't think it or any other presentation concerns need to block the stabilization of the attribute itself – I don't believe the output of the rustdoc falls under the stability guarantees, so we can always fix that later.

nagisa avatar May 07 '21 16:05 nagisa

I actually recently saw a case of the doc-cfg hint being rendered on some items when no doc(cfg()) attribute is applied to those items or any of their parents.

The items in question are all of the methods on this type: https://docs.rs/ruma/0.0.3/ruma/serde/struct.Raw.html The doc(cfg()) attribute being rendered does exist in the ruma crate, but only in one place: https://docs.rs/ruma/0.0.3/src/ruma/lib.rs.html#103

jplatte avatar May 07 '21 17:05 jplatte

One thing that may be nice would be the ability to provide user-defined text for the "x". I use a number of special features like thread_impl="c11". While these typically don't appear in the public api, having "This is only supported on thread implementation c11" in internal documentation, rather than "This is only supported on thread_impl="c11"" might be nice. Not necessarily a blocking feature, though. The way I'd imagine this would be an optional second argument that gives a user-defined representation for the cfg key. In the above case, you'd get #[doc(cfg(thread_impl="c11","thread implementation"))] or something similar.

chorman0773 avatar Aug 22 '21 17:08 chorman0773

Do you want to show the cfg message on both the type and the impl? I'm having trouble understanding the use-case - when would that be necessary?

I just hit a case where I'd like the cfg message on the derived impl but not the type (the derive attribute itself is applied in a cfg_attr attribute). In particular, it's a no_std library that optionally derives some std-only traits if the "std" feature is enabled. With doc_cfg, all my explicit impls of std-only traits are correctly documented as such; but I can't similarly annotate derived ones.

eggyal avatar Oct 07 '21 03:10 eggyal

I can't similarly annotate derived ones.

I don't think this can be fixed on rustdoc's end; rust doesn't allow users to apply attributes to derived traits. We're planning to make doc(cfg) enabled by default for any #[cfg] attribute, would that solve your issue? https://github.com/rust-lang/rust/pull/89596

jyn514 avatar Oct 07 '21 07:10 jyn514

We're planning to make doc(cfg) enabled by default for any #[cfg] attribute, would that solve your issue?

It certainly would!

eggyal avatar Oct 07 '21 08:10 eggyal