Skip to content

[rustdoc] Update doc_cfg hide/show syntax#157871

Open
GuillaumeGomez wants to merge 8 commits into
rust-lang:mainfrom
GuillaumeGomez:doc_cfg-syntax
Open

[rustdoc] Update doc_cfg hide/show syntax#157871
GuillaumeGomez wants to merge 8 commits into
rust-lang:mainfrom
GuillaumeGomez:doc_cfg-syntax

Conversation

@GuillaumeGomez

@GuillaumeGomez GuillaumeGomez commented Jun 13, 2026

Copy link
Copy Markdown
Member

View all comments

Part of #43781.

As discussed at the all-hands with the rustdoc team, we decided to follow the check-cfg syntax. So this PR implements it.

Considering @Urgau made the check-cfg implementation, I'll set them as reviewer here.

r? @Urgau

@rustbot

rustbot commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_hir/src/attrs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-rustdoc-json Area: Rustdoc JSON backend S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Jun 13, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Fixed CI. :)

@Urgau Urgau left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Some changes around none() and we should be in a good place.

View changes since this review

Comment thread compiler/rustc_attr_parsing/src/attributes/doc.rs Outdated
Comment thread compiler/rustc_attr_parsing/src/attributes/doc.rs Outdated
Comment on lines 502 to 515
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq)]
pub enum DocCfgHideShowValue {
Any(Span),
List(ThinVec<(Symbol, Span)>),
}

#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct CfgInfo {
pub name: Symbol,
pub name_span: Span,
pub value: Option<(Symbol, Span)>,
pub struct DocCfgHideShow {
/// If `Some`, then `cfg` without values (like `cfg(windows)`) will be shown/hidden.
/// The `Span` comes from where this value was set.
pub only_key: Option<Span>,
/// The values of this `cfg` to shown/hidden.
pub values: DocCfgHideShowValue,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This representation of the values of #[cfg] diverges from the compiler ExpectedValues for the none value (ie #[cfg(foo)]).

Normally we represent it with an Option<Symbol> where None is the absence of value, but this representation states that a value is only a Symbol and that it cannot be mixed with an "only key", but this ignores that mixed cases like #[cfg(foo)], #[cfg(foo = "12")], #[cfg(foo = "16")], ...

Suggested change
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq)]
pub enum DocCfgHideShowValue {
Any(Span),
List(ThinVec<(Symbol, Span)>),
}
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct CfgInfo {
pub name: Symbol,
pub name_span: Span,
pub value: Option<(Symbol, Span)>,
pub struct DocCfgHideShow {
/// If `Some`, then `cfg` without values (like `cfg(windows)`) will be shown/hidden.
/// The `Span` comes from where this value was set.
pub only_key: Option<Span>,
/// The values of this `cfg` to shown/hidden.
pub values: DocCfgHideShowValue,
}
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq)]
pub enum DocCfgHideShowValue {
Any(Span),
List(ThinVec<(Option<Symbol>, Span)>),
}
#[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct DocCfgHideShow {
/// The values of this `cfg` to shown/hidden.
pub values: DocCfgHideShowValue,
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But with this approach, you need to have two DocCfgHideShow: one to represent cfg(foo) and another to represent cfg(foo = "bla"). Or did I misunderstand your point?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you still only need one DocCfgHideShow and one DocCfgHideShowValue.

The way cfg(foo) would be represented is by having a (None, none_span) inside DocCfgHideShowValue::List.

All the other values, like cfg(foo = "bla") would be (Some("bla"), bla_span)) inside DocCfgHideShowValue::List.

So at the end if you had hide(foo, values(none(), "bla")) it would be represented as:

// imaging this is dbg!()
DocCfgHideShow {
    values: DocCfgHideShowValue::List(vec![
        (None, none_span),
        (Some("bla"), bla_span)),
    ])
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you cannot have an any() and a none() in the same struct then.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any() already implies none(), there is no need for both of them to be specified at the same time.

Also for --check-cfg specifying both is rejected.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you cannot say "all values but only if there is a value"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you cannot say "all values but only if there is a value"?

No, not currently. The same is also not possible with a literal like "bar". There hasn't been a desire to introduce a "all values expect ...".


For the record, we talked about this extensively in DM and ended-up with two possible way forward:

  1. allow conflicting hide(...) and show(...) on the same level: auto_cfg(hide(windows, values(any())), show(windows))
  2. change the effect of show(...) to not take into account hide(...), but instead show everything inside (...) and hide everything else
    • instead of only effecting what was hidden by a previous hide(...)

Both solution would I think work, and I don't have a preference, so feel free to do either of them.

The end goal is to be consistent with --check-cfg: any() implies none().

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with 1. as I find it more elegant and coherent with how cfg works.

Comment thread compiler/rustc_attr_parsing/src/diagnostics.rs Outdated
Comment thread compiler/rustc_attr_parsing/src/diagnostics.rs Outdated
Comment thread tests/rustdoc-html/doc-cfg/hide-inheritance.rs
Comment thread src/librustdoc/json/conversions.rs
@Urgau Urgau added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 16, 2026
@rustbot

rustbot commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

These commits modify tests/rustdoc-json.
rustdoc-json is a public (but unstable) interface.

Please ensure that if you've changed the output:

  • It's intentional.
  • The FORMAT_VERSION in src/librustdoc-json-types is bumped if necessary.

cc @aDotInTheVoid, @obi1kenobi

@rustbot

This comment has been minimized.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Correctly handled values(), added test for values("a", none()), add a rustdoc-json test and updated the book.

@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Well, fmt makes me sad on this one but it's fine. :')

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Implemented the correct handling of values(any()) and remove the show/hide conflict, allowing cases that were not possible otherwise.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

And because I had to forget something, I updated the docs too. :)

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

rustbot commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@GuillaumeGomez

Copy link
Copy Markdown
Member Author

Fixed merge conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-rustdoc-json Area: Rustdoc JSON backend S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants