-
Notifications
You must be signed in to change notification settings - Fork 13.4k
rustdoc: hide #[repr]
if it isn't part of the public ABI
#116882
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
base: master
Are you sure you want to change the base?
rustdoc: hide #[repr]
if it isn't part of the public ABI
#116882
Conversation
r? @notriddle (rustbot has picked a reviewer for you, use r? to override) |
Some changes occurred in src/librustdoc/clean/types.rs cc @camelid |
This comment has been minimized.
This comment has been minimized.
1608e1c
to
0461b26
Compare
Some changes occurred in GUI tests. |
0461b26
to
79bb50a
Compare
src/librustdoc/clean/types.rs
Outdated
|| 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() |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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,
}

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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
#[repr(...)]
if it isn't part of the public ABI#[repr]
if it isn't part of the public ABI
There was a problem hiding this 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.
☔ The latest upstream changes (presumably #126788) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this 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.
79bb50a
to
dc27ca1
Compare
I think it's good like this. Like @dtolnay mentioned, we can always add new rules later on. Should we start the 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. |
Thinking back to past discussions, one reason for being liberal in showing / conservative in hiding 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., |
☔ The latest upstream changes (presumably #129403) made this pull request unmergeable. Please resolve the merge conflicts. |
@rfcbot resolve positive-bugs in cargo-semver-check |
This comment was marked as off-topic.
This comment was marked as off-topic.
…InTheVoid rustdoc JSON: Don't apply `#[repr]` privacy heuristics Split out from rust-lang#116882. Context: rust-lang#116882 (comment). Partially reverts rust-lang#138018. cc `@obi1kenobi` r? aDotInTheVoid or rustdoc
…InTheVoid rustdoc JSON: Don't apply `#[repr]` privacy heuristics Split out from rust-lang#116882. Context: rust-lang#116882 (comment). Partially reverts rust-lang#138018. cc `@obi1kenobi` r? aDotInTheVoid or rustdoc
16e731a
to
2cd93b1
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
2cd93b1
to
94911f1
Compare
We now also consider @rustbot review |
Checking if there's noticeable query invocation overhead. |
This comment has been minimized.
This comment has been minimized.
…c, r=<try> rustdoc: hide `#[repr]` if it isn't part of the public ABI Follow-up to #115439. Unblocks #116743, CC `@dtolnay.` Fixes #128364. Fixes #137440. Only display the representation `#[repr(REPR)]` (where `REPR` is not `Rust` or `transparent`) of a given type if the type is not `#[non_exhaustive]`, if none of its variants (incl. the synthetic variants of structs) are `#[doc(hidden)]` or `#[non_exhaustive]` and if 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)]` and of `#[non_exhaustive]` when checking whether to show `repr(transparent)` or not.
This comment has been minimized.
This comment has been minimized.
Just checking: will this affect the JSON output as well, or only HTML? Also, I wasn't able to find any discussion of why e.g. |
I'm not married to the non-exhaustive logic, it was suggested here: #116882 (review) |
As previously discussed, we don't apply these heuristics if the output format is JSON. |
Thanks! It didn't look to me like it was affected either, but I wanted to err on the not-
This is totally not my area of responsibility, so feel free to decide what you think is best. But here's my counter-argument. Say I'm building a state machine that represents some computational work being performed on a cluster, something like GitHub Actions for example. There are different states jobs could be part of: #[repr(i8)]
pub enum JobState {
NotStarted,
Scheduling,
Running,
Completed,
Errored,
} I want it to be public API that this enum is What I'd like to commit to in the public API is this:
If Between this case and the |
Finished benchmarking commit (5e6424b): comparison URL. Overall result: no relevant changes - no action neededBenchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf. @bors rollup=never Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)Results (primary 5.1%, secondary -2.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 757.216s -> 756.086s (-0.15%) |
Follow-up to #115439.
Unblocks #116743, CC @dtolnay.
Fixes #128364.
Fixes #137440.
Only display the representation
#[repr(REPR)]
(whereREPR
is notRust
ortransparent
) of a given type if the type is not#[non_exhaustive]
, none of its variants (incl. the synthetic variants of structs) are#[doc(hidden)]
or#[non_exhaustive]
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)]
and of#[non_exhaustive]
when checking whether to showrepr(transparent)
or not.