Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

fmease
Copy link
Member

@fmease fmease commented Oct 18, 2023

Follow-up to #115439.
Unblocks #116743, CC @dtolnay.

Fixes #66401.
Fixes #128364.
Fixes #137440.

Only display the representation #[repr(REPR)] (where REPR is not Rust or transparent) of a given type if none of its variants (incl. the synthetic variants of structs) are #[doc(hidden)] and all of its fields are public and not #[doc(hidden)] since it's likely not meant to be considered part of the public ABI otherwise.

--document-{private,hidden}-items works as expected in this context, too.

Moreover, we now also factor in the presence of #[doc(hidden)] when checking whether to show repr(transparent) or not.

@rustbot

This comment was marked as outdated.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Oct 18, 2023
@rustbot

This comment was marked as resolved.

@fmease fmease added relnotes Marks issues that should be documented in the release notes of the next release. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. labels Oct 18, 2023
@rust-log-analyzer

This comment has been minimized.

@fmease fmease force-pushed the rustdoc-generalized-priv-repr-heuristic branch from 1608e1c to 0461b26 Compare October 18, 2023 10:24
@rustbot
Copy link
Collaborator

rustbot commented Oct 18, 2023

Some changes occurred in GUI tests.

cc @GuillaumeGomez

@fmease fmease force-pushed the rustdoc-generalized-priv-repr-heuristic branch from 0461b26 to 79bb50a Compare October 18, 2023 10:41
|| if adt.is_enum() {
// FIXME(fmease): Should we take the visibility of fields of variants into account?
// FIXME(fmease): `any` or `all`?
adt.variants().is_empty()
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 I'd go for any in both cases.

Copy link
Member Author

@fmease fmease Oct 18, 2023

Choose a reason for hiding this comment

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

@RalfJung, does it sound good to you as well to consider the repr public if there exists at least one struct field that is public (there might be private and hidden ones) (if we have a struct) or if there exists at least one non-hidden enum variant (if we have an enum)? (With the extra rule that empty structs and enums also render the repr public).

Or should all fields (current version of this PR) and enum variants be public for the repr to be public?

Copy link
Member

@RalfJung RalfJung Oct 18, 2023

Choose a reason for hiding this comment

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

Usually for structs, if there is at least one private field then we say you can't rely on the struct staying how it is. For instance if your repr(transparent) relies on another type being a ZST and that type has at least one private field, we warn about that (and we eventually want to make that an error).

So I'd say the same should go for the repr. If any field is private, then the repr is (by default) private.

Copy link
Member Author

@fmease fmease Oct 18, 2023

Choose a reason for hiding this comment

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

Thanks, that makes sense! What about enum variants? Can users still make certain assumptions about the repr of an enum if some but not all of its variants are private or hidden?

Copy link
Member

Choose a reason for hiding this comment

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

There's no such things as private enum variants (unfortunately).

Copy link
Member

Choose a reason for hiding this comment

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

on a struct with a doc(hidden) field, should the repr be shown?

Here is an example of what goes wrong if you show repr on a struct with doc(hidden) field.

#[repr(C)]
pub struct Struct {
    pub first: u8,
    #[doc(hidden)]
    pub second: u16,
    pub third: u8,
}
Screenshot 2023-10-18 at 3 41 44 PM

Rustdoc purports a repr(C) struct in which the first byte is first, the second byte is third, and some other fields follow. Given the Rust-like syntax in which rustdoc shows #[repr(C)], this feels misleading. For a struct that is actually this:

#[repr(C)]
pub struct Struct {
    pub first: u8,
    pub third: u8,
    // ... other fields ...
}

one would expect they can cast &Struct to &[u8; 2] and read first and third from it. If they do that in this case though, they get UB from looking at a padding byte.

I think this would be a useful bar to keep in mind as a minimum desirable property; rustdoc should not show a repr in such a way that misleads reader about reality. That does not necessarily need to mean hiding such reprs, though that might be the most expedient path forward. Alternatively rustdoc could be more discerning about placing the /*private field*/ comment in between the correct fields when there is a repr.

Copy link
Member Author

@fmease fmease Oct 19, 2023

Choose a reason for hiding this comment

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

Hmm, do we already track this in a GitHub issue? With the introduction of core::mem::offset_of, it feels like we should up the priority of this issue. If I remember correctly, it'd need quite a bit of rewiring inside rustdoc to render /* private field */ in the correct order for repr(C) structs since those fields are stripped early at the moment.

Copy link
Member Author

@fmease fmease Oct 19, 2023

Choose a reason for hiding this comment

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

RalfJung, re taking doc(hidden) on variants into account when computing the visibility of a repr, I've included that in the heuristic to hide the repr(u8) on core::ffi::c_void which has consists of two doc(hidden) enum variants.

Copy link
Member

@RalfJung RalfJung Oct 19, 2023

Choose a reason for hiding this comment

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

Sounds to me then like we'd want to hide the repr as soon as there is any hidden field (just like we hide it as soon as there is any private field) -- both for struct and enum (and union).

Copy link
Member

Choose a reason for hiding this comment

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

Seems like there is more to discuss. I'll add it to the next rustdoc team meeting agenda.

@fmease fmease added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 22, 2023
@fmease fmease changed the title rustdoc: hide #[repr(...)] if it isn't part of the public ABI rustdoc: hide #[repr] if it isn't part of the public ABI Nov 6, 2023
Copy link
Member

@camelid camelid left a comment

Choose a reason for hiding this comment

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

In discussing this as part of the rustdoc meeting, I realized we probably need to account for whether #[non_exhaustive] has been applied to the struct/enum/etc. If it is, then the API isn't stable.

@bors
Copy link
Collaborator

bors commented Jun 24, 2024

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

Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

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

This appears to be stalled on everyone agreeing on a comprehensive set of rules.

Since I ran into this again today in #128364, I'll try to suggest a way to make progress again: Is it possible we can agree to err on the side of not showing repr? Let's make rustdoc render repr in only the most incontrovertible circumstances: everything is pub, nothing is hidden, there is at least 1 field, there is at least one variant, etc. Feel free to add as many other restrictions here as it takes until everyone agrees that we've reached an overestimation of what the actual rules should be.

After that, we can incrementally agree to additional deliberate cases where repr should be made part of the documented API of a type. Each of these can be FCP'd with the team if needed.

The current state of erring on the side of rendering repr in too many cases that have not been agreed to is unfortunate.

@fmease fmease added rla-silenced Silences rust-log-analyzer postings to the PR it's added on. and removed S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). labels Jul 29, 2024
@fmease fmease force-pushed the rustdoc-generalized-priv-repr-heuristic branch from 79bb50a to dc27ca1 Compare July 29, 2024 23:06
@GuillaumeGomez
Copy link
Member

I think it's good like this. Like @dtolnay mentioned, we can always add new rules later on. Should we start the FCP?

@fmease
Copy link
Member Author

fmease commented Jul 30, 2024

FCP

Not quite yet, I still need to update the approach, PR description and PR itself :) I'll do so in a moment. I've only rebased.

@fmease
Copy link
Member Author

fmease commented Jul 31, 2024

Thinking back to past discussions, one reason for being liberal in showing / conservative in hiding #[repr(...)] was the fact that there's currently no way to override this heuristic, i.e., to force rustdoc to show the repr. Ideas about a #[doc(repr(...))] were floating around.

Without it, users would need to declare this information in prose instead.

Thinking aloud, I guess it does make sense as a first step even if it's not the greatest (e.g., repr packed and C can be meaningful (as part of the public ABI) even if e.g. later fields are private/hidden as they don't necessarily influence the alignment and thus the offset of earlier public fields (for e.g., core::mem::offset_of)).

@bors

This comment was marked as resolved.

@rust-rfcbot
Copy link
Collaborator

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

@fmease fmease added S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. and removed S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). labels Sep 25, 2025
Escape "special characters" (e.g., double quotes `"` and line breaks `\n`).
Escape HTML.

Lastly, add regression tests and clean up existing tests.
@fmease fmease force-pushed the rustdoc-generalized-priv-repr-heuristic branch from 940fb08 to 85c193a Compare September 25, 2025 09:51
@rustbot
Copy link
Collaborator

rustbot commented Sep 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.

@rust-rfcbot rust-rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Sep 25, 2025
@rust-rfcbot
Copy link
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

This will be merged soon.

@GuillaumeGomez
Copy link
Member

Time to merge, thanks everyone!

@bors r=rustdoc rollup

@bors
Copy link
Collaborator

bors commented Sep 25, 2025

📌 Commit 85c193a has been approved by rustdoc

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 25, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Sep 25, 2025
…pr-heuristic, r=rustdoc

rustdoc: hide `#[repr]` if it isn't part of the public ABI

> [!IMPORTANT]
> Temporarily stacked on top of PR rust-lang#146527; only the last commit is relevant!

Follow-up to rust-lang#115439.
Unblocks rust-lang#116743, CC `@dtolnay.`

Fixes rust-lang#66401.
Fixes rust-lang#128364.
Fixes rust-lang#137440.

Only display the representation `#[repr(REPR)]` (where `REPR` is not `Rust` or `transparent`) of a given type if none of its variants (incl. the synthetic variants of structs) are `#[doc(hidden)]` and all of its fields are public and not `#[doc(hidden)]` since it's likely not meant to be considered part of the public ABI otherwise.

`--document-{private,hidden}-items` works as expected in this context, too.

Moreover, we now also factor in the presence of `#[doc(hidden)]` when checking whether to show `repr(transparent)` or not.
bors added a commit that referenced this pull request Sep 25, 2025
Rollup of 8 pull requests

Successful merges:

 - #116882 (rustdoc: hide `#[repr]` if it isn't part of the public ABI)
 - #135771 ([rustdoc] Add support for associated items in "jump to def" feature)
 - #141032 (avoid violating `slice::from_raw_parts` safety contract in `Vec::extract_if`)
 - #142401 (Add proper name mangling for pattern types)
 - #146293 (feat: non-panicking `Vec::try_remove`)
 - #146859 (BTreeMap: Don't leak allocators when initializing nodes)
 - #146924 (Add doc for `NonZero*` const creation)
 - #146933 (Make `render_example_with_highlighting` return an `impl fmt::Display`)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit a39d513 into rust-lang:master Sep 25, 2025
10 checks passed
@rustbot rustbot added this to the 1.92.0 milestone Sep 25, 2025
rust-timer added a commit that referenced this pull request Sep 25, 2025
Rollup merge of #116882 - fmease:rustdoc-generalized-priv-repr-heuristic, r=rustdoc

rustdoc: hide `#[repr]` if it isn't part of the public ABI

> [!IMPORTANT]
> Temporarily stacked on top of PR #146527; only the last commit is relevant!

Follow-up to #115439.
Unblocks #116743, CC ``@dtolnay.``

Fixes #66401.
Fixes #128364.
Fixes #137440.

Only display the representation `#[repr(REPR)]` (where `REPR` is not `Rust` or `transparent`) of a given type if none of its variants (incl. the synthetic variants of structs) are `#[doc(hidden)]` and all of its fields are public and not `#[doc(hidden)]` since it's likely not meant to be considered part of the public ABI otherwise.

`--document-{private,hidden}-items` works as expected in this context, too.

Moreover, we now also factor in the presence of `#[doc(hidden)]` when checking whether to show `repr(transparent)` or not.
@fmease fmease deleted the rustdoc-generalized-priv-repr-heuristic branch September 26, 2025 02:18
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Sep 26, 2025
Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#116882 (rustdoc: hide `#[repr]` if it isn't part of the public ABI)
 - rust-lang/rust#135771 ([rustdoc] Add support for associated items in "jump to def" feature)
 - rust-lang/rust#141032 (avoid violating `slice::from_raw_parts` safety contract in `Vec::extract_if`)
 - rust-lang/rust#142401 (Add proper name mangling for pattern types)
 - rust-lang/rust#146293 (feat: non-panicking `Vec::try_remove`)
 - rust-lang/rust#146859 (BTreeMap: Don't leak allocators when initializing nodes)
 - rust-lang/rust#146924 (Add doc for `NonZero*` const creation)
 - rust-lang/rust#146933 (Make `render_example_with_highlighting` return an `impl fmt::Display`)

r? `@ghost`
`@rustbot` modify labels: rollup
Zalathar added a commit to Zalathar/rust that referenced this pull request Sep 28, 2025
Library: Remove remaining private `#[repr]` workarounds

With rust-lang#116882 finally merged, gating these `repr`s behind cfg `not(doc)` is no longer necessary to achieve a private repr.

Follow up to rust-lang#128046 (that was enabled via rust-lang#115439). With that, rust-lang#116743 is now fully realized at long last.

cc `@dtolnay`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Sep 28, 2025
Library: Remove remaining private `#[repr]` workarounds

With rust-lang#116882 finally merged, gating these `repr`s behind cfg `not(doc)` is no longer necessary to achieve a private repr.

Follow up to rust-lang#128046 (that was enabled via rust-lang#115439). With that, rust-lang#116743 is now fully realized at long last.

cc ``@dtolnay``
rust-timer added a commit that referenced this pull request Sep 28, 2025
Rollup merge of #147095 - fmease:libprivrepr, r=dtolnay

Library: Remove remaining private `#[repr]` workarounds

With #116882 finally merged, gating these `repr`s behind cfg `not(doc)` is no longer necessary to achieve a private repr.

Follow up to #128046 (that was enabled via #115439). With that, #116743 is now fully realized at long last.

cc ``@dtolnay``
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rustdoc-json Area: Rustdoc JSON backend disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. 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. to-announce Announce this issue on triage meeting
Projects
None yet