mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Rollup merge of #124410 - RalfJung:path-buf-transmute, r=Nilstrieb
PathBuf: replace transmuting by accessor functions
The existing `repr(transparent)` was anyway insufficient as `OsString` was not `repr(transparent)`. And furthermore, on Windows it was blatantly wrong as `OsString` wraps `Wtf8Buf` which is a `repr(Rust)` type with 2 fields:
51a7396ad3/library/std/src/sys_common/wtf8.rs (L131-L146)
So let's just be honest about what happens and add accessor methods that make this abstraction-breaking act of PathBuf visible on the APIs that it pierces through.
Fixes https://github.com/rust-lang/rust/issues/124409
This commit is contained in:
commit
7cbba53396
@ -532,6 +532,12 @@ impl OsString {
|
||||
let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
|
||||
unsafe { Box::from_raw(rw) }
|
||||
}
|
||||
|
||||
/// Part of a hack to make PathBuf::push/pop more efficient.
|
||||
#[inline]
|
||||
pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
|
||||
self.inner.as_mut_vec_for_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1158,12 +1158,6 @@ 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")]
|
||||
// `PathBuf::as_mut_vec` current implementation relies
|
||||
// on `PathBuf` being layout-compatible with `Vec<u8>`.
|
||||
// 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,
|
||||
}
|
||||
@ -1171,7 +1165,7 @@ pub struct PathBuf {
|
||||
impl PathBuf {
|
||||
#[inline]
|
||||
fn as_mut_vec(&mut self) -> &mut Vec<u8> {
|
||||
unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
|
||||
self.inner.as_mut_vec_for_path_buf()
|
||||
}
|
||||
|
||||
/// Allocates an empty `PathBuf`.
|
||||
|
@ -196,6 +196,12 @@ impl Buf {
|
||||
pub fn into_rc(&self) -> Rc<Slice> {
|
||||
self.as_slice().into_rc()
|
||||
}
|
||||
|
||||
/// Part of a hack to make PathBuf::push/pop more efficient.
|
||||
#[inline]
|
||||
pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Slice {
|
||||
|
@ -158,6 +158,12 @@ impl Buf {
|
||||
pub fn into_rc(&self) -> Rc<Slice> {
|
||||
self.as_slice().into_rc()
|
||||
}
|
||||
|
||||
/// Part of a hack to make PathBuf::push/pop more efficient.
|
||||
#[inline]
|
||||
pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
|
||||
self.inner.as_mut_vec_for_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl Slice {
|
||||
|
@ -468,6 +468,12 @@ impl Wtf8Buf {
|
||||
let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
|
||||
Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false }
|
||||
}
|
||||
|
||||
/// Part of a hack to make PathBuf::push/pop more efficient.
|
||||
#[inline]
|
||||
pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new WTF-8 string from an iterator of code points.
|
||||
|
Loading…
Reference in New Issue
Block a user