-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Hide #[repr(transparent)]
where the field is non-public
#90435
Comments
Is there consensus that this is a good thing to do? I understand that the thing that @jhpratt wanted to do with |
The reason I was advised against it is because the attribute is only meaningful if you are able to know what the inner type is. While something like The |
I mean, that's not true, is it? It makes some very explicit promises. Consider struct ffi_foo;
#[repr(transparent)]
pub struct Foo {
inner: UnsafeCell<ffi_foo>,
}
impl Foo {
pub fn go_kazoo(&self) {
unsafe { ffi_foo_go_kazoo(self.inner.get()) }
}
}
impl<'a> From<&'a ffi_foo> for &'a Foo {
fn from(x: &'a ffi_foo) -> Self {
// SAFETY: types have identical layout and ffi_foo is thread-safe
unsafe { std::mem::transmute(x) }
}
} Maybe that example is misguided, but it still stands that |
Ignoring the fact that the example you provided is unsound, I see no reference to the inner type of |
Which part is unsound? Ignoring the details of my example, though, here's the Nomicon regarding
|
Yeah @jhpratt is correct. Just a repr(transparent) attribute does not give any public-facing guarantee when the field isn't pub. Individual data structures may document a commitment that their layout may be publicly relied on, but that is simply not repr(transparent). Currently this kind of thing is just written in prose but this came up as well in rust-lang/unsafe-code-guidelines#302 (comment) about whether there should be some machine-readable way. |
Okay I see what you're saying. To put it in my own words, the set of all The unfortunate thing is that this split is currently not documented very well if at all. And as shown above, the Nomicon describes But given that the Nomicon is written how it is, it seems possible that there are already crates that elide any additional prose and rely solely on the presence of |
I disagree that the nomicon's description refers to publicly transparent. It's describing guarantees that the language makes to the module/crate that contains the type. Nothing in there is about what guarantees the module/crate makes to its downstream users. |
Hm, maybe not explicitly. But when I read it, it seems strongly implied.
Nothing on that page, nor in the parent page, nor even in the Reference page on layouts, suggests to me that these rules only apply to the module/crate where the type is defined. My own intuition additionally tells me that the layout of a type is a property that is true for any crate in which the type is used. Perhaps there's some detail that I'm missing when I read it, but really, if this is an important distinction, then it should be made more clearly. I'm more than happy to have my misconceptions ironed out through discussion, but I would wager that other noobs like me will walk away thinking the exact same things given the current text, and that's the real problem to me. |
To me that's precisely why this issue was created and should be resolved. |
I agree that nobody has any business attempting to transmute a PathBuf, but the non-pub nature of structures like NonZeroU8 is necessary to uphold the invariants - otherwise safe code could simply write a 0 to the field. There will need to be some other attribute - possibly under rustdoc:: - to indicate whether the choice of inner type is stable. |
Incidentally related: IOW: I think any |
I'm in favor of this change. For example, seeing something like this in the docs: #[repr(transparent)]
pub struct Foo<T> { /* private fields */ } Does not guarantee that #[repr(transparent)]
pub struct Foo<T> {
content: Vec<T>,
}
A quick search through GH yields some examples of this happening:
I think this might be too radical. |
They apply globally, if you pin your dependency. But nothing in any of those documents says anything about how library authors are allowed to evolve their type definitions while being semver-compliant. It's perfectly semver-compatible to, for example, remove the So yes, the layout of a type is a property that is true anywhere, but how that layout may change in the future looks very different from inside a module/crate and from the outside, and |
Note that privacy is not sufficient to cover all cases where #[repr(u8)]
pub enum Color {
BLACK = 0b00;
RED = 0b01;
BLUE = 0b10;
PURPLE = 0b11;
} I might want to make use of the bit-patterns of this enum for some algorithm within the crate, but not guarantee to users that the discriminant values are stable. (Though this is not solely about And getting back to mod v1_0 {
pub struct Foo(());
pub struct Bar(i32);
#[repr(transparent)]
pub struct Murky {
pub foo: Foo,
pub bar: Bar,
}
}
mod v1_1 {
pub struct Foo(i32);
pub struct Bar(());
#[repr(transparent)]
pub struct Murky {
pub foo: Foo,
pub bar: Bar,
}
}
None of this says that rustdoc shouldn't hide |
Imo one should have to explicitly opt into making any |
Anyway I think there is not much harm fixing the issue as stated, and we can figure out a principled approach without breaking stuff in the future. I think we should only do this for transparent and not C, since it is useful knowing if an opaque struct is repr(C) |
It's pretty clear-cut with For |
The current situation is that some people consider then always public but others do not. See e.g. #90435 (comment)
So no you cannot just assume they are public when you see them in a random library and the type has private fields. That's already the case today. rustdoc just does not reflect that.
|
Can you elaborate a bit more on this? I can interpret this sentence in a couple different ways and I'm not sure what the right parse is. :) |
Yes, agreed, but I think informally enough of the ecosystem relies on this for |
Okay, so what if we – for the time being – show In pseudo code: fields.find(is_non_zst)
.map_or_else(|| fields.any(is_pub), is_pub) I can spin up a PR relatively quickly if you like this approach. If you consider this rule too complicated, I can also just go for |
This seems fine.
I assume you mean |
|
That sounds like a bug to me... I mean, this would also break the documented intended use case of the Is there an issue for this, or, if this is the intended behavior, is there any discussion/explanation on why and an issue to add it to the docs? Totally caught me by surprise. |
Yeah, it's bad. It falls out of the way cross-crate inlining and compiling works. Fixing it is actually going to be pretty complicated. I couldn't find a bug report for it (not very many people use |
Seems like I misinterpreted your comment. I'm gonna pick up the work on it again then. |
I've now opened #115439. |
Rollup merge of rust-lang#115439 - fmease:rustdoc-priv-repr-transparent-heuristic, r=GuillaumeGomez rustdoc: hide `#[repr(transparent)]` if it isn't part of the public ABI Fixes rust-lang#90435. This hides `#[repr(transparent)]` when the non-1-ZST field the struct is "transparent" over is private. CC `@RalfJung` Tentatively nominating it for the release notes, feel free to remove the nomination. `@rustbot` label needs-fcp relnotes A-rustdoc-ui
Now that rust-lang#90435 seems to have been resolved.
Now that rust-lang#90435 seems to have been resolved.
Fix some `#[cfg_attr(not(doc), repr(..))]` Now that rust-lang#90435 seems to have been resolved.
Fix some `#[cfg_attr(not(doc), repr(..))]` Now that rust-lang#90435 seems to have been resolved.
Rollup merge of rust-lang#128046 - GrigorenkoPV:90435, r=tgross35 Fix some `#[cfg_attr(not(doc), repr(..))]` Now that rust-lang#90435 seems to have been resolved.
Per @dtolnay in #72841:
As such, we should consider hiding
#[repr(transparent)]
when the field is not otherwise visible. This should not be the case when--document-private-items
is passed for reasons that should be obvious.This will affect some stdlib structs such as
NonZeroU8
@rustbot label +A-docs +C-enhancement +T-rustdoc
The text was updated successfully, but these errors were encountered: