Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make cfg imply doc(cfg) #79341

Closed
wants to merge 5 commits into from
Closed

Conversation

Nemo157
Copy link
Member

@Nemo157 Nemo157 commented Nov 23, 2020

This is only active when the doc_cfg feature is active.

The implicit cfg can be overridden via #[doc(cfg(...))], so e.g. to hide a #[cfg] you can use something like:

#[cfg(unix)]
#[doc(cfg(all()))]
pub struct Unix;

By adding #![doc(cfg_hide(foobar))] to the crate attributes the cfg #[cfg(foobar)] (and only that exact cfg) will not be implicitly treated as a doc(cfg) to render a message in the documentation.

TODO:

  • Test against some popular libraries, especially those already using doc(cfg)
  • Update doc(cfg) docs
  • Add doc(cfg_hide) docs

@rust-highfive
Copy link
Collaborator

r? @ollie27

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 23, 2020
@petrochenkov
Copy link
Contributor

petrochenkov commented Nov 23, 2020

Is this relying on the fact that #[cfg] expansion leaves the #[cfg] attribute in place?
Then it relies on an undocumented bug that I was actually going to fix soon.

Here's what the reference say:

If the predicate is true, the thing is rewritten to not have the cfg attribute on it.

(Which matches the intention, but not reality, because cfg currently behaves unlike any other active attribute and keeps itself during expansion.)

@Nemo157
Copy link
Member Author

Nemo157 commented Nov 23, 2020

For my own crates that use doc-cfg this works perfectly, I can remove the doc(cfg) lines and get the correct features rendered.

For tokio 0.3.4 this adds a bunch of Unix cfgs to the docs. There are a couple of cfg(not(loom)) that need suppressing, and some kind of bug to do with the cfg displayed for tokio::{main, test} that I need to look into.

For syn 1.0.50 this exposes quite a few more cfgs that seem correct, it probably needs looking at by a syn dev to see if they really should be exposed. There's also a couple WebAssembly cfgs that need suppressing.

@Nemo157
Copy link
Member Author

Nemo157 commented Nov 23, 2020

Is this relying on the fact that #[cfg] expansion leaves the #[cfg] attribute in place?

Yeah, probably. Would there be some way to look back at the original AST and see what #[cfg] were applied to a specific node if they get removed? Or could rustdoc run some pass before #[cfg] expansion to save this off into a side-table?

@jyn514 jyn514 added F-doc_cfg `#![feature(doc_cfg)]` T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Nov 23, 2020
@petrochenkov petrochenkov self-assigned this Nov 23, 2020
@petrochenkov
Copy link
Contributor

Would there be some way to look back at the original AST and see what #[cfg] were applied to a specific node if they get removed? Or could rustdoc run some pass before #[cfg] expansion to save this off into a side-table?

Perhaps the best way to recover this functionality would be to expand #[cfg(TRUE_PREDICATE)] ITEM into #[doc(cfg(TRUE_PREDICATE))] ITEM rather than to just ITEM in rustdoc mode.
(The key property is that the produced attribute should be inert, unlike cfg itself.)

Feel free to experiment with the impact of this change on real life code, but I'd like to block actually merging this for ~1.5 months until I get to implementing the cfg changes.

This is only active when the doc_cfg feature is active.

Changing behavior depending on feature gate (rather than just producing an error) is not a good practice, this means stabilization will be a (potentially breaking) change in behavior.

@petrochenkov petrochenkov removed their assignment Nov 25, 2020
@petrochenkov petrochenkov added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 25, 2020
@jyn514
Copy link
Member

jyn514 commented Dec 3, 2020

Changing behavior depending on feature gate (rather than just producing an error) is not a good practice, this means stabilization will be a (potentially breaking) change in behavior.

How would you suggest to do this instead? Unconditionally adding doc(cfg) will give an error that the feature gate isn't active, even projects just using cfg (which is stable).

@bors
Copy link
Contributor

bors commented Dec 31, 2020

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

@JohnCSimon
Copy link
Member

@rustbot modify labels: -S-waiting-on-review +S-waiting-on-author

@rustbot rustbot 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 Jan 19, 2021
@jyn514
Copy link
Member

jyn514 commented Jan 19, 2021

@JohnCSimon as far as I know this is still waiting on response to #79341 (comment).

@jyn514 jyn514 added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 19, 2021
@petrochenkov
Copy link
Contributor

I planned to work on cfg changes during holidays, but #79078 didn't made it in time, so cfg changes are going to be deferred to uncertain future, and I don't want to block this PR on them anymore.
It is always possible to make cfg behavior depending on whether we are running rustdoc or not, if it becomes really necessary.

If making the feature gate non-behavior-changing is hard, then it can be made behavior changing.
Still mind that stabilization will change behavior in this case.

r? @jyn514

@rust-highfive rust-highfive assigned jyn514 and unassigned petrochenkov and ollie27 Jan 20, 2021
Copy link
Member

@jyn514 jyn514 left a comment

Choose a reason for hiding this comment

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

This looks good to me, but someone from T-libs may want to take a look at the rendered docs.

cfg changes are going to be deferred to uncertain future, and I don't want to block this PR on them anymore.

Thank you ❤️ If it makes you feel better, I think the doc(cfg) desugaring you mentioned should be possible even with the feature gate as long as there's a way to tell whether the attribute was injected by the compiler or not.

For tokio 0.3.4 this adds a bunch of Unix cfgs to the docs. There are a couple of cfg(not(loom)) that need suppressing, and some kind of bug to do with the cfg displayed for tokio::{main, test} that I need to look into.

Did you get a chance to look at the bug?

For syn 1.0.50 this exposes quite a few more cfgs that seem correct, it probably needs looking at by a syn dev to see if they really should be exposed. There's also a couple WebAssembly cfgs that need suppressing.

I'll start a try build in just a second so people can test this locally.

TODO: Update doc(cfg) docs, Add doc(cfg_hide) docs

Please add these when you get a chance. This also needs a rebase.

compiler/rustc_feature/src/active.rs Outdated Show resolved Hide resolved
library/alloc/src/lib.rs Outdated Show resolved Hide resolved
Comment on lines +61 to +80
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64",
target_has_atomic = "8",
target_has_atomic = "16",
target_has_atomic = "32",
target_has_atomic = "64",
target_has_atomic = "ptr",
target_has_atomic_equal_alignment = "8",
target_has_atomic_equal_alignment = "16",
target_has_atomic_equal_alignment = "32",
target_has_atomic_equal_alignment = "64",
target_has_atomic_equal_alignment = "ptr",
target_has_atomic_load_store = "8",
target_has_atomic_load_store = "16",
target_has_atomic_load_store = "32",
target_has_atomic_load_store = "64",
target_has_atomic_load_store = "ptr",
Copy link
Member

Choose a reason for hiding this comment

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

Why hide these?

Copy link
Member Author

Choose a reason for hiding this comment

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

These, along with target_has_atomic_ptr, are unstable cfg. While I think it would be really nice to have this all documented on the items, I don't think the doc(cfg) presentation of them is good enough. I'll attach a screenshot of what it looks like with them unhidden.

I also think it might make sense to enhance doc(cfg_hide) to support specifying just the key of key-value cfg expressions so that these aren't duplicated for each size.

@@ -272,7 +272,8 @@ impl Clean<Item> for doctree::Module<'_> {

impl Clean<Attributes> for [ast::Attribute] {
fn clean(&self, cx: &DocContext<'_>) -> Attributes {
Attributes::from_ast(cx.sess().diagnostic(), self, None)
let doc_cfg_active = cx.tcx.features().doc_cfg;
Attributes::from_ast(cx.sess().diagnostic(), self, None, doc_cfg_active, &cx.hidden_cfg)
Copy link
Member

Choose a reason for hiding this comment

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

Why put this on Attributes instead of calling tcx.features() on demand?

Copy link
Member

Choose a reason for hiding this comment

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

I found why - you use it directly in from_ast, not after Attributes is constructed. It's either this or pass a tcx; this seems fine.

fn single(self) -> Option<Self::Item> {
let mut iter = self.into_iter();
let item = iter.next()?;
iter.next().is_none().then_some(())?;
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a little too cute :P

Suggested change
iter.next().is_none().then_some(())?;
if iter.next().is_some() {
return None;
}

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 think I'll likely scrap the whole SingleExt extension trait as the diagnostics for 0 and >1 items should be different.

@jyn514
Copy link
Member

jyn514 commented Jan 20, 2021

@bors try

@crlf0710 crlf0710 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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 20, 2021
@jhpratt
Copy link
Member

jhpratt commented Apr 2, 2021

Friendly ping @Nemo157 — what's the status of this?

@JohnCSimon JohnCSimon 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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 18, 2021
@JohnCSimon
Copy link
Member

Ping from triage:
@Nemo157 - can you please post your status?

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors

This comment has been minimized.

@jyn514 jyn514 changed the title Make cfg implicitly imply doc(cfg) Make cfg imply doc(cfg) Apr 26, 2021
Nemo157 and others added 5 commits April 26, 2021 10:23
This is only active when the `doc_cfg` feature is active.

The implicit cfg can be overridden via #[doc(cfg(...))], so e.g. to
hide a #[cfg] you can use something like:

```rust
 #[cfg(unix)]
 #[doc(cfg(all()))]
pub struct Unix;
```

(since `all()` is always true, it is never shown in the docs)
By adding #![doc(cfg_hide(foobar))] to the crate attributes the cfg
 #[cfg(foobar)] (and _only_ that _exact_ cfg) will not be implicitly
treated as a doc(cfg) to render a message in the documentation.
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
    Finished release [optimized] target(s) in 10.63s
tidy check
tidy: Skipping binary file check, read-only filesystem
Checking which error codes lack tests...
tidy error: /checkout/src/librustdoc/html/render/print_item.rs:293: TODO is deprecated; use FIXME
* highest error code: E0781
Found 515 error codes
Found 0 error codes with no tests
Done!
Done!
* 330 features
some tidy checks failed


command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/rust-tidy" "/checkout" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "/checkout/obj/build" "16"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test --stage 2 src/tools/tidy
Build completed unsuccessfully in 0:00:13

@bors
Copy link
Contributor

bors commented Apr 27, 2021

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

@bstrie
Copy link
Contributor

bstrie commented May 12, 2021

@Nemo157 , is this PR still being pursued?

@jyn514
Copy link
Member

jyn514 commented May 13, 2021

@bstrie this is the last update I heard: https://discord.com/channels/442252698964721669/459149231702278154/836259493741985854

I really don't think I will get time to work on it anytime soon, so if you want to do it I can help review (in which case it might make sense to close that PR and open a new one)

@bstrie
Copy link
Contributor

bstrie commented Jun 2, 2021

Would someone like to make a tracking issue so that this can be closed, then?

@GuillaumeGomez
Copy link
Member

I took this PR, rebased it and updated the code so that it can work with current rustdoc in #89596.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Oct 7, 2021
…jyn514

Make cfg imply doc(cfg)

This is a reopening of rust-lang#79341, rebased and modified a bit (we made a lot of refactoring in rustdoc's types so they needed to be reflected in this PR as well):

 * `hidden_cfg` is now in the `Cache` instead of `DocContext` because `cfg` information isn't stored anymore on `clean::Attributes` type but instead computed on-demand, so we need this information in later parts of rustdoc.
 * I removed the `bool_to_options` feature (which makes the code a bit simpler to read for `SingleExt` trait implementation.
 * I updated the version for the feature.

There is only one thing I couldn't figure out: [this comment](rust-lang#79341 (comment))

> I think I'll likely scrap the whole `SingleExt` extension trait as the diagnostics for 0 and >1 items should be different.

How/why should they differ?

EDIT: this part has been solved, the current code was fine, just needed a little simplification.

cc `@Nemo157`
r? `@jyn514`

Original PR description:

This is only active when the `doc_cfg` feature is active.

The implicit cfg can be overridden via `#[doc(cfg(...))]`, so e.g. to hide a `#[cfg]` you can use something like:

```rust
#[cfg(unix)]
#[doc(cfg(all()))]
pub struct Unix;
```

By adding `#![doc(cfg_hide(foobar))]` to the crate attributes the cfg `#[cfg(foobar)]` (and _only_ that _exact_ cfg) will not be implicitly treated as a `doc(cfg)` to render a message in the documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-doc_cfg `#![feature(doc_cfg)]` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs-api Relevant to the library API 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.