rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

RFC for doc_cfg, doc_cfg_auto, doc_cfg_hide and doc_cfg_show features

Open GuillaumeGomez opened this issue 1 year ago • 18 comments

tracking issue

cc @rust-lang/rustdoc

Rendered

GuillaumeGomez avatar May 09 '24 14:05 GuillaumeGomez

I'm in favour of this but I would recommend clarifying the #[cfg(any(doc, ...))] trick in the guide-level explanation a bit further, since folks reading it might be misled into thinking that rustdoc will just ignore conditional compilation entirely to report things, which isn't true; it just shows the conditions when they're met.

clarfonthey avatar May 09 '24 20:05 clarfonthey

Applied first round of review comments. Thanks everyone!

GuillaumeGomez avatar May 13 '24 12:05 GuillaumeGomez

Updated the syntax for auto_cfg to instead accept true or false.

Removed restriction on doc(cfg()) which was marked as not being able to be used as a crate-level attribute as it currently works using it as such, so doesn't seem there is a good enough reason to change this behaviour.

GuillaumeGomez avatar May 21 '24 12:05 GuillaumeGomez

I have re-read the reference part again, but I still don't understand why there are so many attributes.

  • Why is #![doc(auto_cfg = true)] necessary if it is the default?
  • Why is #![doc(auto_cfg = false)] necessary if it is equivalent to #![doc(cfg_hide(any()))]?
    • If it is not equivalent, then why it needs to do something different? It would be better if they were equivalent and auto_cfg didn't need to exist.
  • Why is #![doc(cfg_show(...))] necessary if it is equivalent to #![doc(cfg(...))]?
    • If it is not equivalent, then why it needs to do something different? It would be better if they were equivalent and cfg_show didn't need to exist.

It looks like having just doc(cfg) and doc(cfg_hide) would be enough to both explicitly enable and disable whatever configs are necessary, with cfg acting as a default.

petrochenkov avatar May 28 '24 15:05 petrochenkov

A couple more questions.

  • Is #[doc(cfg)] currently allowed on an item without #[cfg]? What are the semantics?
    • I'd expect this to be allowed making cfg_show redundant as in the previous comment.
  • Is it possible to show a cfg on an item, but hide it on all children of that item? (Without putting attributes on all those children individually.)

petrochenkov avatar May 28 '24 16:05 petrochenkov

I have re-read the reference part again, but I still don't understand why there are so many attributes.

  • Why is #![doc(auto_cfg = true)] necessary if it is the default?

Because future possibilities include to make this attribute work not only at crate-level but also on any item. And based on this discussion, I think it'll part of this RFC.

  • Why is #![doc(auto_cfg = false)] necessary if it is equivalent to #![doc(cfg_hide(any()))]?

cfg_hide doesn't work like cfg: it only accepts "items". However, the RFC is very unclear about it, so I'll add it in the RFC.

  • If it is not equivalent, then why it needs to do something different? It would be better if they were equivalent and auto_cfg didn't need to exist.

I have to admit I didn't think about cfg_show and cfg_hide to work this way at all. I'm not sure it's a good idea though. For example, how should we handle this case:

cfg_hide(any(windows, not(unix)))

How do we interpret the not(unix)? As a whole or should it invert the "hide unix"? So for simplicity, that's why not, any and all are not supported in cfg_hide and cfg_show and why we have cfg_auto.

  • Why is #![doc(cfg_show(...))] necessary if it is equivalent to #![doc(cfg(...))]?

It is not. As mentioned in the RFC:

It only applies to #[doc(auto_cfg = true)], not to #[doc(cfg(...))].

  • If it is not equivalent, then why it needs to do something different? It would be better if they were equivalent and cfg_show didn't need to exist.

Because they both fill different role. You might want to add your own "doc cfg" information to either override what auto_doc_cfg generates or add your own information.

A couple more questions.

  • Is #[doc(cfg)] currently allowed on an item without #[cfg]? What are the semantics?

The RFC says:

This attribute provides a standardized format to override #[cfg()] attributes to document conditionally available items. ... This attribute has the same syntax as conditional compilation

So the semantics are covered I think. The RFC didn't make it clear it works with and without cfg on the item though, so I'll add a clarification.

  • I'd expect this to be allowed making cfg_show redundant as in the previous comment.

  • Is it possible to show a cfg on an item, but hide it on all children of that item? (Without putting attributes on all those children individually.)

I think I see why you mention it. I suppose you talk a case like:

#[cfg(windows)]
mod module {
    #![doc(cfg_hide(windows))]

    fn item() {}
}

In this case, since the doc(cfg_hide(windows)) is also an attribute of module, it should impact module. I think we should say that inner doc(cfg_hide) and doc(cfg_show) attributes don't impact the item if they are inner attributes.

GuillaumeGomez avatar May 28 '24 19:05 GuillaumeGomez

So only remains the question:

#[cfg(windows)]
mod module {
    #![doc(cfg_hide(windows))]

    fn item() {}
}

How to allow cfg(windows) to be displayed on module while having it hidden on its children? I think what the RFC offer is good enough:

#[cfg(windows)]
#[doc(cfg(windows)] // Will be displayed all the time
#[doc(cfg_hide(windows))] // Hides `windows` from `doc(auto_cfg)` rendering on `module` and its children
pub mod module {
    #[cfg(windows)] // Not displayed because of `cfg_hide(windows)`!
    pub fn item() {}
}

So I'd be willing to not change anything in this regard.

GuillaumeGomez avatar May 28 '24 19:05 GuillaumeGomez

Just wanted to make sure that my comment above (https://github.com/rust-lang/rfcs/pull/3631#pullrequestreview-2048876838) wasn't missed, as there has been no response or acknowledgement :slightly_smiling_face:

jhpratt avatar May 28 '24 22:05 jhpratt

I don't understand your comments. Do you have an example of what you would want to do?

GuillaumeGomez avatar May 29 '24 14:05 GuillaumeGomez

For an overly simplified case, see https://github.com/jhpratt/doc-cfg-demo

Running cargo +nightly doc --all-features on alpha will incorrectly say that alpha::S::foo is "Available on crate feature foo-method only." I hadn't checked this in a while, but previously it would have no annotation whatsoever. Ideally, the feature resolver would be utilized to show the correct annotation — it relies on the feature beta-foo-method.

This situation is quite common with façade crates and is the sole reason I have not migrated large amounts of code from time to time-core. Were I to do this, I could remove ~1000 LOC (off the top of my head) from time-macros that is currently duplicated.

jhpratt avatar May 30 '24 05:05 jhpratt

Okay so if I understand correctly what you say, reexported items should only show cfgs from the reexport's point of view (so to speak)? That sounds reasonable. Once you confirm it, I'll update the RFC.

GuillaumeGomez avatar Jun 27 '24 12:06 GuillaumeGomez

Effectively, yes. My point of view is "what does a consumer of the library care about". That would mean showing them what feature they need to enable such that the item is present, taking into account feature transitivity, etc.

jhpratt avatar Jun 27 '24 21:06 jhpratt

I added an example but normally it was covered. For the current case, this is a bug that should be solved.

GuillaumeGomez avatar Jun 28 '24 14:06 GuillaumeGomez

I think with this all questions/comments were answered/resolved?

GuillaumeGomez avatar Jun 28 '24 14:06 GuillaumeGomez

As long as we agree on intended behavior, and it seems we do, then I'm satisfied. As I'd said above, the behavior had changed since I originally checked; it previously had no annotation.

Feel free to use that example as a rustdoc test whenever that gets fixed, by the way. No credit necessary.

jhpratt avatar Jun 29 '24 05:06 jhpratt

I definitely plan to. :3

GuillaumeGomez avatar Jun 29 '24 09:06 GuillaumeGomez

I think it's time to start the FCP then.

@rfcbot fcp merge

GuillaumeGomez avatar Jul 04 '24 09:07 GuillaumeGomez

Team member @GuillaumeGomez has proposed to merge this. The next step is review by the rest of the tagged team members:

  • [x] @GuillaumeGomez
  • [x] @Manishearth
  • [x] @Nemo157
  • [ ] @aDotInTheVoid
  • [x] @camelid
  • [x] @fmease
  • [ ] @jsha
  • [x] @notriddle

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

rfcbot avatar Jul 04 '24 09:07 rfcbot

Friendly ping @Manishearth, @Nemo157, @aDotInTheVoid, @camelid, @jsha, this is blocking progress on stabilizing #[doc(cfg(...))] etc.

madsmtm avatar Oct 25 '24 12:10 madsmtm

I don't think my old concern that auto_cfg and cfg_show are confusing since they are new terms using cfg in different spots has been addressed.

I'm not going to block the RFC on that, but I don't want to approve it myself. If everyone else is fine with it that's fine, but I would like to see if the overall api surface can be made easier to remember.

Manishearth avatar Oct 25 '24 17:10 Manishearth

I applied suggestions from @Manishearth about the hide/show attributes: since they're only applied on the auto_cfg feature cfgs, it makes more sense to embed them in the auto_cfg attribute (imo).

I also added an explanation about why cfged out items are not included by rustdoc.

GuillaumeGomez avatar Nov 27 '24 16:11 GuillaumeGomez

@GuillaumeGomez nice! Should the syntax for auto_cfg then be doc(auto_cfg) and doc(auto_cfg = false) (with = true being accepted but not the primary documented syntax)?

Manishearth avatar Nov 27 '24 17:11 Manishearth

You mean for doc(auto_cfg) to be equivalent to doc(auto_cfg = true), making the = true optional?

GuillaumeGomez avatar Nov 27 '24 18:11 GuillaumeGomez

@GuillaumeGomez yes, so basically this means:

  • doc(auto_cfg) = auto on
  • doc(auto_cfg(show(..)) = auto on, and show stuff
  • doc(auto_cfg = false) = turn it off
  • doc(auto_cfg = true) = auto on, but not the primary documented syntax

the idea is that this way we have consistency: if you mention auto_cfg it enables it, you don't have to explicitly put = true if you're using show and can use a single invocation.

Manishearth avatar Nov 27 '24 19:11 Manishearth

Not a super big fan of the implicit but it also kinda makes sense. Does it also include doc(auto_cfg(hide(...)))? Following the logic "if auto_cfg without = is used, it's enabled", it'd mean that auto_cfg(hide) would also enable auto_cfg. I'm fine with it but just want to confirm with you before updating the RFC.

GuillaumeGomez avatar Nov 27 '24 19:11 GuillaumeGomez

Yeah, hide doesn't make any sense without auto_cfg.

I mostly don't want to mix the = and the () syntax too much, and this way most normal users only use the () syntax

Manishearth avatar Nov 27 '24 20:11 Manishearth

At the very least, doc(auto_cfg) should work. My whole thrust here is to make the syntax relatively uniform and memorable.

Manishearth avatar Nov 27 '24 20:11 Manishearth

Ok, updating the RFC to reflect it then. 👍

GuillaumeGomez avatar Nov 27 '24 22:11 GuillaumeGomez

Added the new syntax (allowing to have no argument in auto_cfg) and also the new behaviour for auto_cfg(hide(...)) and auto_cfg(show(...)).

Thanks for the ideas!

GuillaumeGomez avatar Nov 27 '24 23:11 GuillaumeGomez

:bell: This is now entering its final comment period, as per the review above. :bell:

rfcbot avatar Mar 05 '25 17:03 rfcbot