about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-09-17 14:10:50 -0700
committerGitHub <noreply@github.com>2019-09-17 14:10:50 -0700
commitd6f2205ed8460da20f21e959e019d2bc6817cb5a (patch)
treee3db80825b82ee7a17d8fd1ac5e35684392ff133 /src/libcore
parentffee7bbf9a3ae1cff2bdf3cb17d3f5d8b01951c0 (diff)
parentab6e108644474ece91711e889cff7d36a0adf7f0 (diff)
downloadrust-d6f2205ed8460da20f21e959e019d2bc6817cb5a.tar.gz
rust-d6f2205ed8460da20f21e959e019d2bc6817cb5a.zip
Rollup merge of #64436 - llogiq:transmute-docs, r=RalfJung
improve Vec example soundness in mem::transmute docs

The previous version of the `Vec` example had a case of questionable soundness, because at one point `v_orig` was aliased.

r? @RalfJung
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/intrinsics.rs28
1 files changed, 17 insertions, 11 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d145f2212f9..ecff40a7597 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -845,21 +845,26 @@ extern "rust-intrinsic" {
     ///
     /// ```
     /// let store = [0, 1, 2, 3];
-    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    /// let v_orig = store.iter().collect::<Vec<&i32>>();
+    ///
+    /// // clone the vector as we will reuse them later
+    /// let v_clone = v_orig.clone();
     ///
     /// // Using transmute: this is Undefined Behavior, and a bad idea.
     /// // However, it is no-copy.
     /// let v_transmuted = unsafe {
-    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
-    ///         v_orig.clone())
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
     /// };
     ///
+    /// let v_clone = v_orig.clone();
+    ///
     /// // This is the suggested, safe way.
     /// // It does copy the entire vector, though, into a new array.
-    /// let v_collected = v_orig.clone()
-    ///                         .into_iter()
-    ///                         .map(|r| Some(r))
-    ///                         .collect::<Vec<Option<&i32>>>();
+    /// let v_collected = v_clone.into_iter()
+    ///                          .map(Some)
+    ///                          .collect::<Vec<Option<&i32>>>();
+    ///
+    /// let v_clone = v_orig.clone();
     ///
     /// // The no-copy, unsafe way, still using transmute, but not UB.
     /// // This is equivalent to the original, but safer, and reuses the
@@ -869,11 +874,12 @@ 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 {
-    ///     Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
-    ///                         v_orig.len(),
-    ///                         v_orig.capacity())
+    ///     // 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>,
+    ///                         v_clone.len(),
+    ///                         v_clone.capacity())
     /// };
-    /// std::mem::forget(v_orig);
     /// ```
     ///
     /// Implementing `split_at_mut`: