From 0d21d257c9691983fd51e7d5d9ace4de8933114c Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 22 Oct 2019 13:54:09 -0400 Subject: [PATCH 1/3] Remove unneeded pointer casting --- src/liballoc/string.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 639124e26cc20..108c91fba1ff8 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -194,9 +194,9 @@ use crate::vec::Vec; /// ``` /// use std::mem; /// -/// let story = String::from("Once upon a time..."); +/// let mut story = String::from("Once upon a time..."); /// -/// let ptr = story.as_ptr(); +/// let ptr = story.as_mut_ptr(); /// let len = story.len(); /// let capacity = story.capacity(); /// @@ -209,7 +209,7 @@ use crate::vec::Vec; /// // We can re-build a String out of ptr, len, and capacity. This is all /// // unsafe because we are responsible for making sure the components are /// // valid: -/// let s = unsafe { String::from_raw_parts(ptr as *mut _, len, capacity) } ; +/// let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ; /// /// assert_eq!(String::from("Once upon a time..."), s); /// ``` @@ -676,14 +676,14 @@ impl String { /// use std::mem; /// /// unsafe { - /// let s = String::from("hello"); - /// let ptr = s.as_ptr(); + /// let mut s = String::from("hello"); + /// let ptr = s.as_mut_ptr(); /// let len = s.len(); /// let capacity = s.capacity(); /// /// mem::forget(s); /// - /// let s = String::from_raw_parts(ptr as *mut _, len, capacity); + /// let s = String::from_raw_parts(ptr, len, capacity); /// /// assert_eq!(String::from("hello"), s); /// } From dce8fabc62ed393152c53c65c492c8f3ae324eda Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 22 Oct 2019 15:40:22 -0400 Subject: [PATCH 2/3] Use ManuallyDrop in examples for {Vec,String}::from_raw_parts --- src/liballoc/string.rs | 16 +++++++++------- src/liballoc/vec.rs | 10 +++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 108c91fba1ff8..1d0faeccecf1d 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -194,7 +194,10 @@ use crate::vec::Vec; /// ``` /// use std::mem; /// -/// let mut story = String::from("Once upon a time..."); +/// let story = String::from("Once upon a time..."); +/// +/// // Prevent automatically dropping the String's data +/// let mut story = mem::ManuallyDrop::new(story); /// /// let ptr = story.as_mut_ptr(); /// let len = story.len(); @@ -203,9 +206,6 @@ use crate::vec::Vec; /// // story has nineteen bytes /// assert_eq!(19, len); /// -/// // Now that we have our parts, we throw the story away. -/// mem::forget(story); -/// /// // We can re-build a String out of ptr, len, and capacity. This is all /// // unsafe because we are responsible for making sure the components are /// // valid: @@ -676,13 +676,15 @@ impl String { /// use std::mem; /// /// unsafe { - /// let mut s = String::from("hello"); + /// let s = String::from("hello"); + /// + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// /// let ptr = s.as_mut_ptr(); /// let len = s.len(); /// let capacity = s.capacity(); /// - /// mem::forget(s); - /// /// let s = String::from_raw_parts(ptr, len, capacity); /// /// assert_eq!(String::from("hello"), s); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 6350b189c5faa..c8fb897123475 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -389,7 +389,11 @@ impl Vec { /// use std::ptr; /// use std::mem; /// - /// let mut v = vec![1, 2, 3]; + /// let v = vec![1, 2, 3]; + /// + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); /// /// // Pull out the various important pieces of information about `v` /// let p = v.as_mut_ptr(); @@ -397,10 +401,6 @@ impl Vec { /// let cap = v.capacity(); /// /// unsafe { - /// // Cast `v` into the void: no destructor run, so we are in - /// // complete control of the allocation to which `p` points. - /// mem::forget(v); - /// /// // Overwrite memory with 4, 5, 6 /// for i in 0..len as isize { /// ptr::write(p.offset(i), 4 + i); From 6600cf604091a99bba990d41b93885b40c02a97d Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 22 Oct 2019 12:48:52 -0400 Subject: [PATCH 3/3] Add {String,Vec}::into_raw_parts --- src/liballoc/string.rs | 33 +++++++++++++++++++++++++++++++++ src/liballoc/vec.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/libcore/intrinsics.rs | 1 + 3 files changed, 73 insertions(+) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1d0faeccecf1d..d9927c642b2d8 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -196,6 +196,7 @@ use crate::vec::Vec; /// /// let story = String::from("Once upon a time..."); /// +// FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent automatically dropping the String's data /// let mut story = mem::ManuallyDrop::new(story); /// @@ -647,6 +648,37 @@ impl String { decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect() } + /// Decomposes a `String` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the string (in bytes), and the allocated capacity of the data + /// (in bytes). These are the same arguments in the same order as + /// the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `String`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `String` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: #method.from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let s = String::from("hello"); + /// + /// let (ptr, len, cap) = s.into_raw_parts(); + /// + /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; + /// assert_eq!(rebuilt, "hello"); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { + self.vec.into_raw_parts() + } + /// Creates a new `String` from a length, capacity, and pointer. /// /// # Safety @@ -678,6 +710,7 @@ impl String { /// unsafe { /// let s = String::from("hello"); /// + // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent automatically dropping the String's data /// let mut s = mem::ManuallyDrop::new(s); /// diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index c8fb897123475..641f9eafa8d23 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -358,6 +358,44 @@ impl Vec { } } + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: #method.from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = mem::ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + /// Creates a `Vec` directly from the raw components of another vector. /// /// # Safety @@ -391,6 +429,7 @@ impl Vec { /// /// let v = vec![1, 2, 3]; /// + // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control /// // of the allocation. /// let mut v = mem::ManuallyDrop::new(v); diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b240d059114eb..4655d39fb8f1f 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -874,6 +874,7 @@ extern "rust-intrinsic" { /// // the original inner type (`&i32`) to the converted inner type /// // (`Option<&i32>`), so read the nomicon pages linked above. /// let v_from_raw = unsafe { + // FIXME Update this when vec_into_raw_parts is stabilized /// // Ensure the original vector is not dropped. /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone); /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,