Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
std: add some missing repr(transparent)
  • Loading branch information
RalfJung committed Aug 14, 2023
commit f887f5a9c6393d1f3eef98cdf13b4491e27b22e4
3 changes: 3 additions & 0 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ use crate::str;
// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`.
// Anyway, `CStr` representation and layout are considered implementation detail, are
// not documented and must not be relied upon.
// For now we just hide this from rustdoc, technically making our doc test builds rely on
// unspecified layout assumptions. We are std, so we can get away with that.
#[cfg_attr(not(doc), repr(transparent))]
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure this affects doc tests? I tried this on a new library and it compiled, but failed the assertion:

/// ```
/// assert!(cfg!(doc));
/// ```
pub struct Foo(u32);

I do expect your cfg will affect how rustdoc parses the source when it looks for doctests, but not the actual library or doctest build.

Copy link
Member

Choose a reason for hiding this comment

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

Another way to see that doc tests are not affected:

/// ```
/// use lib::Foo;
/// use std::mem::align_of;
///
/// assert!(!cfg!(doc));
/// assert_eq!(align_of::<Foo>(), align_of::<u32>());
/// ```
#[cfg_attr(doc, repr(packed))]
pub struct Foo(u32);

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I guess doctests are built with cfg(doctest)... nice! So this is actually a reasonable approach then.

pub struct CStr {
// FIXME: this should not be represented with a DST slice but rather with
// just a raw `c_char` along with some form of marker to make
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ impl crate::sealed::Sealed for OsString {}
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
// Anyway, `OsStr` representation and layout are considered implementation details, are
// not documented and must not be relied upon.
// For now we just hide this from rustdoc, technically making our doc test builds rely on
// unspecified layout assumptions. We are std, so we can get away with that.
#[cfg_attr(not(doc), repr(transparent))]
pub struct OsStr {
inner: Slice,
}
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,9 @@ impl FusedIterator for Ancestors<'_> {}
// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
// Anyway, `PathBuf` representation and layout are considered implementation detail, are
// not documented and must not be relied upon.
// For now we just hide this from rustdoc, technically making our doc test builds rely on
// unspecified layout assumptions. We are std, so we can get away with that.
#[cfg_attr(not(doc), repr(transparent))]
pub struct PathBuf {
inner: OsString,
}
Expand Down Expand Up @@ -1989,6 +1992,9 @@ impl AsRef<OsStr> for PathBuf {
// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
// Anyway, `Path` representation and layout are considered implementation detail, are
// not documented and must not be relied upon.
// For now we just hide this from rustdoc, technically making our doc test builds rely on
// unspecified layout assumptions. We are std, so we can get away with that.
#[cfg_attr(not(doc), repr(transparent))]
pub struct Path {
inner: OsStr,
}
Expand Down
10 changes: 8 additions & 2 deletions library/std/src/sys/wasi/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,20 @@ pub struct WasiFd {
fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout.
// We decorate our `IoSliceMut` with `repr(transparent)` (see `io.rs`), and
// `crate::io::IoSliceMut` is a `repr(transparent)` wrapper around our type, so this is
// guaranteed.
unsafe { mem::transmute(a) }
}

fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout.
// We decorate our `IoSlice` with `repr(transparent)` (see `io.rs`), and
// `crate::io::IoSlice` is a `repr(transparent)` wrapper around our type, so this is
// guaranteed.
unsafe { mem::transmute(a) }
}

Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys_common/wtf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ impl Wtf8Buf {
/// Converts this `Wtf8Buf` into a boxed `Wtf8`.
#[inline]
pub fn into_box(self) -> Box<Wtf8> {
// SAFETY: relies on `Wtf8` being `repr(transparent)`.
unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
}

Expand Down Expand Up @@ -511,6 +512,7 @@ impl Extend<CodePoint> for Wtf8Buf {
/// Similar to `&str`, but can additionally contain surrogate code points
/// if they’re not in a surrogate pair.
#[derive(Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Wtf8 {
bytes: [u8],
}
Expand Down