Skip to content

Commit e6c378f

Browse files
committed
Auto merge of rust-lang#125966 - schvv31n:impl_os_string_pathbuf_leak, r=workingjubilee
Implement `os_string_pathbuf_leak` implementation of rust-lang#125965 ACP: rust-lang/libs-team#389 [ Accepted ]
2 parents 67454f5 + 20f15f4 commit e6c378f

File tree

7 files changed

+72
-0
lines changed

7 files changed

+72
-0
lines changed

std/src/ffi/os_str.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,25 @@ impl OsString {
533533
unsafe { Box::from_raw(rw) }
534534
}
535535

536+
/// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
537+
/// `&'a mut OsStr`.
538+
///
539+
/// The caller has free choice over the returned lifetime, including 'static.
540+
/// Indeed, this function is ideally used for data that lives for the remainder of
541+
/// the program’s life, as dropping the returned reference will cause a memory leak.
542+
///
543+
/// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
544+
/// unused capacity that is not part of the returned slice. If you want to discard excess
545+
/// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
546+
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
547+
///
548+
/// [`into_boxed_os_str`]: Self::into_boxed_os_str
549+
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
550+
#[inline]
551+
pub fn leak<'a>(self) -> &'a mut OsStr {
552+
OsStr::from_inner_mut(self.inner.leak())
553+
}
554+
536555
/// Part of a hack to make PathBuf::push/pop more efficient.
537556
#[inline]
538557
pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {

std/src/ffi/os_str/tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ fn test_os_string_clear() {
2323
assert_eq!(0, os_string.inner.as_inner().len());
2424
}
2525

26+
#[test]
27+
fn test_os_string_leak() {
28+
let os_string = OsString::from("have a cake");
29+
let (len, cap) = (os_string.len(), os_string.capacity());
30+
let leaked = os_string.leak();
31+
assert_eq!(leaked.as_encoded_bytes(), b"have a cake");
32+
unsafe { drop(String::from_raw_parts(leaked as *mut OsStr as _, len, cap)) }
33+
}
34+
2635
#[test]
2736
fn test_os_string_capacity() {
2837
let os_string = OsString::with_capacity(0);

std/src/path.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,25 @@ impl PathBuf {
12261226
self
12271227
}
12281228

1229+
/// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents,
1230+
/// `&'a mut Path`.
1231+
///
1232+
/// The caller has free choice over the returned lifetime, including 'static.
1233+
/// Indeed, this function is ideally used for data that lives for the remainder of
1234+
/// the program’s life, as dropping the returned reference will cause a memory leak.
1235+
///
1236+
/// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include
1237+
/// unused capacity that is not part of the returned slice. If you want to discard excess
1238+
/// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead.
1239+
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
1240+
///
1241+
/// [`into_boxed_path`]: Self::into_boxed_path
1242+
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
1243+
#[inline]
1244+
pub fn leak<'a>(self) -> &'a mut Path {
1245+
Path::from_inner_mut(self.inner.leak())
1246+
}
1247+
12291248
/// Extends `self` with `path`.
12301249
///
12311250
/// If `path` is absolute, it replaces the current path.

std/src/path/tests.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ fn into() {
126126
assert_eq!(static_cow_path, owned_cow_path);
127127
}
128128

129+
#[test]
130+
fn test_pathbuf_leak() {
131+
let string = "/have/a/cake".to_owned();
132+
let (len, cap) = (string.len(), string.capacity());
133+
let buf = PathBuf::from(string);
134+
let leaked = buf.leak();
135+
assert_eq!(leaked.as_os_str().as_encoded_bytes(), b"/have/a/cake");
136+
unsafe { drop(String::from_raw_parts(leaked.as_mut_os_str() as *mut OsStr as _, len, cap)) }
137+
}
138+
129139
#[test]
130140
#[cfg(unix)]
131141
pub fn test_decompositions_unix() {

std/src/sys/os_str/bytes.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ impl Buf {
176176
self.inner.extend_from_slice(&s.inner)
177177
}
178178

179+
#[inline]
180+
pub fn leak<'a>(self) -> &'a mut Slice {
181+
unsafe { mem::transmute(self.inner.leak()) }
182+
}
183+
179184
#[inline]
180185
pub fn into_box(self) -> Box<Slice> {
181186
unsafe { mem::transmute(self.inner.into_boxed_slice()) }

std/src/sys/os_str/wtf8.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ impl Buf {
138138
self.inner.shrink_to(min_capacity)
139139
}
140140

141+
#[inline]
142+
pub fn leak<'a>(self) -> &'a mut Slice {
143+
unsafe { mem::transmute(self.inner.leak()) }
144+
}
145+
141146
#[inline]
142147
pub fn into_box(self) -> Box<Slice> {
143148
unsafe { mem::transmute(self.inner.into_box()) }

std/src/sys_common/wtf8.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,11 @@ impl Wtf8Buf {
325325
self.bytes.shrink_to(min_capacity)
326326
}
327327

328+
#[inline]
329+
pub fn leak<'a>(self) -> &'a mut Wtf8 {
330+
unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
331+
}
332+
328333
/// Returns the number of bytes that this string buffer can hold without reallocating.
329334
#[inline]
330335
pub fn capacity(&self) -> usize {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy