Skip to content

Commit

Permalink
Rollup merge of rust-lang#114800 - RalfJung:transparent, r=cuviper
Browse files Browse the repository at this point in the history
std: add some missing repr(transparent)

For some types we don't want to stably guarantee this, so hide the `repr` from rustdoc. This nice approach was suggested by `@thomcc.`
  • Loading branch information
matthiaskrgr authored Aug 15, 2023
2 parents 17c47cf + fe1a034 commit 28295db
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 18 deletions.
8 changes: 4 additions & 4 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ use crate::str;
#[stable(feature = "core_c_str", since = "1.64.0")]
#[rustc_has_incoherent_inherent_impls]
#[lang = "CStr"]
// FIXME:
// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
// on `CStr` being layout-compatible with `[u8]`.
// 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.
// However, `CStr` layout is considered an implementation detail and must not be relied upon. We
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
#[cfg_attr(not(doc), repr(transparent))]
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
8 changes: 4 additions & 4 deletions library/std/src/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ impl crate::sealed::Sealed for OsString {}
/// [conversions]: super#conversions
#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
// `OsStr::from_inner` current implementation relies
// on `OsStr` being layout-compatible with `Slice`.
// 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.
// However, `OsStr` layout is considered an implementation detail and must not be relied upon. We
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
#[cfg_attr(not(doc), repr(transparent))]
pub struct OsStr {
inner: Slice,
}
Expand Down
16 changes: 8 additions & 8 deletions library/std/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1158,12 +1158,12 @@ impl FusedIterator for Ancestors<'_> {}
/// Which method works best depends on what kind of situation you're in.
#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
// `PathBuf::as_mut_vec` current implementation relies
// on `PathBuf` being layout-compatible with `Vec<u8>`.
// 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.
// However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
#[cfg_attr(not(doc), repr(transparent))]
pub struct PathBuf {
inner: OsString,
}
Expand Down Expand Up @@ -1983,12 +1983,12 @@ impl AsRef<OsStr> for PathBuf {
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
// `Path::new` current implementation relies
// on `Path` being layout-compatible with `OsStr`.
// 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.
// However, `Path` layout is considered an implementation detail and must not be relied upon. We
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
#[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

0 comments on commit 28295db

Please sign in to comment.