Description
Consider the following code:
struct ZST;
#[repr(transparent)]
struct TransparentWithManuallyDropZST {
value: i32,
md: std::mem::ManuallyDrop<ZST>, // error: repr_transparent_external_private_fields
zst: ZST, // no error
}
the field md
fires a lint warning:
warning: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> src/lib.rs:7:5
|
7 | md: std::mem::ManuallyDrop<ZST>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `ManuallyDrop<ZST>`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
= note: `#[warn(repr_transparent_external_private_fields)]` on by default
While the spirit of the lint seems reasonable, the docs state:
ManuallyDrop<T>
is guaranteed to have the same layout and bit validity asT
So in this case, it seems like ManuallyDrop
changing size would be a breaking change, and the lint at the very least misleading here. Perhaps an exclusion is needed on this lint for ManuallyDrop
?
More generally, quoting the nomicon:
This repr is only considered part of the public ABI of a type if either the single field is pub, or if its layout is documented in prose. Otherwise, the layout should not be relied upon by other crates.
So, in ManuallyDrop
's case, the single field is not pub, but the layout is documented in prose and so should be considered part of the ABI. Is it possible there are other types out there with such a layout guarantee in prose, which might also be incorrectly flagged by this lint?