Skip to content

Conversation

GuillaumeGomez
Copy link
Member

@GuillaumeGomez GuillaumeGomez commented Mar 24, 2025

Implementation of rust-lang/rfcs#3631.

This implementation actually resulted in a lot of simplifications:

  • All cfg computation is now done in one place: propagate_doc_cfg.rs. Because (trait) impls are not retrieved at the same time as the other items, we cannot perform this computation in the clean process, it needs to be after.
  • Because there is cfg inheritance, we can keep track of them in one place (in propagate_doc_cfg.rs), meaning we don't need to copy an item's attributes to its children anymore. Only exception: impl items. For them we clone only cfg attributes.
  • propagate_doc_cfg.rs is also now much simpler, much less need to keep track of parents, since everything we need is handled by the new CfgInfo type.
  • I also suspect that Cfg::simplify_with could either be removed or at least used directly into propagate_doc_cfg.rs when we compute cfgs. Considering how big the PR already is, I'll do it in a follow-up.

I didn't remove the doc_cfg* features in this PR because some dependencies used in rustc (like stdarch) are using it, so we need to have a nightly released with this PR before I can switch to the new feature.

r? ghost

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) 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 Mar 24, 2025
@rust-log-analyzer

This comment has been minimized.

@petrochenkov
Copy link
Contributor

What remains to be done:

I'd also want to block the stabilization on landing #138844 to avoid a stable rustdoc feature relying on externally observable hacks in rustc.
The crater run in #138844 returned mostly clean, so I expect it to land soon.

@GuillaumeGomez
Copy link
Member Author

Noted! And that will be a nice improvement, thanks!

Just one thing left for the cfg expansion missing: #[cfg_attr(blabla, derive(Debug))]. In this case, the cfg is not kept in the generated derive items. It's been in my TODO list for a long time now. ^^'

@petrochenkov
Copy link
Contributor

Just one thing left for the cfg expansion missing: #[cfg_attr(blabla, derive(Debug))]

Do you mean like in #138515? :)

@GuillaumeGomez
Copy link
Member Author

You're my hero! Gonna need to handle this new attribute then. :)

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented Mar 25, 2025

☔ The latest upstream changes (presumably #138923) made this pull request unmergeable. Please resolve the merge conflicts.

@GuillaumeGomez GuillaumeGomez force-pushed the rfc-3631 branch 2 times, most recently from d88598f to db25eea Compare March 27, 2025 10:18
@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Mar 27, 2025
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented Mar 27, 2025

☔ The latest upstream changes (presumably #138927) made this pull request unmergeable. Please resolve the merge conflicts.

@GuillaumeGomez GuillaumeGomez force-pushed the rfc-3631 branch 2 times, most recently from b8cb424 to b581ce1 Compare March 28, 2025 23:54
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez GuillaumeGomez force-pushed the rfc-3631 branch 4 times, most recently from 71369a1 to fbee8a9 Compare April 1, 2025 15:52
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented Aug 24, 2025

☔ The latest upstream changes (presumably #137229) made this pull request unmergeable. Please resolve the merge conflicts.

@GuillaumeGomez
Copy link
Member Author

Fixed merge conflict.

@rustbot
Copy link
Collaborator

rustbot commented Aug 25, 2025

This PR was rebased onto a different master 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.

@rustbot
Copy link
Collaborator

rustbot commented Aug 25, 2025

⚠️ Warning ⚠️

  • There are issue links (such as #123) in the commit messages of the following commits.
    Please move them to the PR description, to avoid spamming the issues with references to the commit, and so this bot can automatically canonicalize them to avoid issues with subtree.


If no argument is specified (ie `#[doc(auto_cfg)]`), it's the same as writing `#[doc(auto_cfg = true)]`.

### `#[doc(cfg(...))]`
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems a bit odd to have doc(cfg(...)) listed in between two different forms of doc(auto_cfg)

Comment on lines +945 to +947
```text
Available on (Windows or Unix) and non-Unix only.
```
Copy link
Contributor

Choose a reason for hiding this comment

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

This case seems like something that could be improved in the future, but mostly unrelated to the feature being added here

// doesn't matter at this point.
//
// We need to pass this empty `CfgInfo` because `merge_attrs` is used when computing the `cfg`.
let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs, &mut CfgInfo::default());
Copy link
Contributor

Choose a reason for hiding this comment

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

seems slightly inefficient but probably acceptable...

Comment on lines +264 to +268
if !hidden.contains(self) {
Some(self.clone())
} else {
None
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This means that doc(auto_cfg(hide(feature))) will not hide all features... is this the behavior we want?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is the one described in the RFC. We cannot hide just all feature = "" cfgs.

/// This type keeps track of (doc) cfg information as we go down the item tree.
#[derive(Clone, Debug)]
pub(crate) struct CfgInfo {
/// List of `doc(auto_cfg(hide(...)))` cfgs.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// List of `doc(auto_cfg(hide(...)))` cfgs.
/// List of currently active `doc(auto_cfg(hide(...)))` cfgs, minus currently active `doc(auto_cfg(show(...)))` cfgs.

is this correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is indeed!

Some(Arc::new(cfg_info.current_cfg.clone()))
}
} else {
// Since we always want to collect all `cfg` items, we remove the hidden ones afterward.
Copy link
Contributor

Choose a reason for hiding this comment

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

Saying "always" in a branch that is conditionally executed seems a bit confusing imo.

Copy link
Member Author

Choose a reason for hiding this comment

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

True, rewording it.

Comment on lines +84 to +86
if let Attribute::Unparsed(ref mut normal) = attr
&& let [ident] = &*normal.path.segments
{
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we were treating target_feature as doc(cfg(target_feature))? Why do we keep it before and not now?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, the two are different. We handle attributes copy and doc(cfg()) inheritance in different locations as they rely on different rules. doc(cfg()) inherits from the parent item whereas attributes are copied only for reexports.

Comment on lines +12 to +15
#[doc(auto_cfg(hide(true)))] //~ ERROR
#[doc(auto_cfg(hide(42)))] //~ ERROR
#[doc(auto_cfg(hide("a")))] //~ ERROR
#[doc(auto_cfg(hide(foo::bar)))] //~ ERROR
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#[doc(auto_cfg(hide(true)))] //~ ERROR
#[doc(auto_cfg(hide(42)))] //~ ERROR
#[doc(auto_cfg(hide("a")))] //~ ERROR
#[doc(auto_cfg(hide(foo::bar)))] //~ ERROR
#[doc(auto_cfg(hide(true)))] //~ ERROR
#[doc(auto_cfg(hide(42)))] //~ ERROR
#[doc(auto_cfg(hide("a")))] //~ ERROR
#[doc(auto_cfg(hide(foo::bar)))] //~ ERROR
#[doc(auto_cfg = hide(true)] //~ ERROR
#[doc(auto_cfg = 42)] //~ ERROR
#[doc(auto_cfg = "a")] //~ ERROR
#[doc(auto_cfg = foo::bar)] //~ ERROR

more testcases

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't put all of them otherwise it triggers earlier rustc errors:

error: expected unsuffixed literal, found `hide`
  --> $DIR/doc-cfg.rs:16:18
   |
LL | #[doc(auto_cfg = hide(true))]
   |                  ^^^^
   |
help: surround the identifier with quotation marks to make it into a string literal
   |
LL | #[doc(auto_cfg = "hide"(true))]
   |                  +    +

error: expected unsuffixed literal, found `foo`
  --> $DIR/doc-cfg.rs:19:18
   |
LL | #[doc(auto_cfg = foo::bar)]
   |                  ^^^
   |
help: surround the identifier with quotation marks to make it into a string literal
   |
LL | #[doc(auto_cfg = "foo"::bar)]
   |                  +   +

error: aborting due to 2 previous errors

@@ -0,0 +1,22 @@
// Checks that `cfg` are correctly applied on inlined reexports.
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this also check that cfgs don't get applied on non-inlined reexports?

Comment on lines +1 to +2
#![feature(doc_cfg)]

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean target_feature will no longer result in any note on stable rustdoc? Or will we still display the attribute itself?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nothing will be displayed. That's what happens when a PR changing a lot of things waits for too long. ^^'

@fmease fmease assigned lolbinarycat and unassigned fmease Aug 25, 2025
@fmease
Copy link
Member

fmease commented Aug 26, 2025

I didn't remove the doc_cfg* features in this PR because some dependencies used in rustc (like stdarch) are using it, so we need to have a nightly released with this PR before I can switch to the new feature.

That's good in any case 👍 This PR should just update the implementation according to the latest version of the merged RFC.

I don't know if we have written that down in our new Forge docs (I hope so) but a feature stabilization would of course require another FCP, the one from the RFC isn't sufficient for that. Moreover, not stabilizing here / now / immediately allows us to gather more user feedback (esp. since the changes made by this PR are non-trivial). Heck, we could even issue a "call for testing" on the official blog – anything to make the eventual stabilization run as smoothly as possible.

@GuillaumeGomez
Copy link
Member Author

I don't know if we have written that down in our new Forge docs (I hope so) but a feature stabilization would of course require another FCP, the one from the RFC isn't sufficient for that. Moreover, not stabilizing here / now / immediately allows us to gather more user feedback (esp. since the changes made by this PR are non-trivial). Heck, we could even issue a "call for testing" on the official blog – anything to make the eventual stabilization run as smoothly as possible.

I was planning to keep it unstable for at least a few months and to enable it in some big crates to gather some usage and see if everything is working as expected.

And in any case: any stabilization PR must go through FCP (we should check if we mention that in the forge ^^').

@GuillaumeGomez
Copy link
Member Author

Oh also: applied suggestions from @lolbinarycat. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) A-run-make Area: port run-make Makefiles to rmake.rs 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.