From 9fe9041cc8eddaed402d17aa4facb2ce8f222e95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io>
Date: Tue, 22 Oct 2024 21:14:22 +0200
Subject: [PATCH] Implement `From<&mut {slice}>` for `Box/Rc/Arc<{slice}>`

---
 library/alloc/src/boxed/convert.rs | 45 ++++++++++++++++++++++++++++++
 library/alloc/src/ffi/c_str.rs     | 31 ++++++++++++++++++++
 library/alloc/src/rc.rs            | 40 ++++++++++++++++++++++++++
 library/alloc/src/sync.rs          | 40 ++++++++++++++++++++++++++
 library/std/src/ffi/os_str.rs      | 27 ++++++++++++++++++
 library/std/src/path.rs            | 28 +++++++++++++++++++
 6 files changed, 211 insertions(+)

diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs
index 19a583ca546e4..4430fff66775c 100644
--- a/library/alloc/src/boxed/convert.rs
+++ b/library/alloc/src/boxed/convert.rs
@@ -109,6 +109,29 @@ impl<T: Clone> From<&[T]> for Box<[T]> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl<T: Clone> From<&mut [T]> for Box<[T]> {
+    /// Converts a `&mut [T]` into a `Box<[T]>`
+    ///
+    /// This conversion allocates on the heap
+    /// and performs a copy of `slice` and its contents.
+    ///
+    /// # Examples
+    /// ```rust
+    /// // create a &mut [u8] which will be used to create a Box<[u8]>
+    /// let mut array = [104, 101, 108, 108, 111];
+    /// let slice: &mut [u8] = &mut array;
+    /// let boxed_slice: Box<[u8]> = Box::from(slice);
+    ///
+    /// println!("{boxed_slice:?}");
+    /// ```
+    #[inline]
+    fn from(slice: &mut [T]) -> Box<[T]> {
+        Self::from(&*slice)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl<T: Clone> From<Cow<'_, [T]>> for Box<[T]> {
@@ -147,6 +170,28 @@ impl From<&str> for Box<str> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut str> for Box<str> {
+    /// Converts a `&mut str` into a `Box<str>`
+    ///
+    /// This conversion allocates on the heap
+    /// and performs a copy of `s`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut original = String::from("hello");
+    /// let original: &mut str = &mut original;
+    /// let boxed: Box<str> = Box::from(original);
+    /// println!("{boxed}");
+    /// ```
+    #[inline]
+    fn from(s: &mut str) -> Box<str> {
+        Self::from(&*s)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, str>> for Box<str> {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index d7e99f4a1a638..d91682b796e4f 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -772,6 +772,16 @@ impl From<&CStr> for Box<CStr> {
     }
 }
 
+#[cfg(not(test))]
+#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut CStr> for Box<CStr> {
+    /// Converts a `&mut CStr` into a `Box<CStr>`,
+    /// by copying the contents into a newly allocated [`Box`].
+    fn from(s: &mut CStr) -> Box<CStr> {
+        Self::from(&*s)
+    }
+}
+
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, CStr>> for Box<CStr> {
     /// Converts a `Cow<'a, CStr>` into a `Box<CStr>`,
@@ -910,6 +920,17 @@ impl From<&CStr> for Arc<CStr> {
     }
 }
 
+#[cfg(target_has_atomic = "ptr")]
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut CStr> for Arc<CStr> {
+    /// Converts a `&mut CStr` into a `Arc<CStr>`,
+    /// by copying the contents into a newly allocated [`Arc`].
+    #[inline]
+    fn from(s: &mut CStr) -> Arc<CStr> {
+        Arc::from(&*s)
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
     /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
@@ -932,6 +953,16 @@ impl From<&CStr> for Rc<CStr> {
     }
 }
 
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut CStr> for Rc<CStr> {
+    /// Converts a `&mut CStr` into a `Rc<CStr>`,
+    /// by copying the contents into a newly allocated [`Rc`].
+    #[inline]
+    fn from(s: &mut CStr) -> Rc<CStr> {
+        Rc::from(&*s)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl Default for Rc<CStr> {
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 9fdd51ce331fb..3128716497b4e 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2651,6 +2651,26 @@ impl<T: Clone> From<&[T]> for Rc<[T]> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl<T: Clone> From<&mut [T]> for Rc<[T]> {
+    /// Allocates a reference-counted slice and fills it by cloning `v`'s items.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use std::rc::Rc;
+    /// let mut original = [1, 2, 3];
+    /// let original: &mut [i32] = &mut original;
+    /// let shared: Rc<[i32]> = Rc::from(original);
+    /// assert_eq!(&[1, 2, 3], &shared[..]);
+    /// ```
+    #[inline]
+    fn from(v: &mut [T]) -> Rc<[T]> {
+        Rc::from(&*v)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "shared_from_slice", since = "1.21.0")]
 impl From<&str> for Rc<str> {
@@ -2670,6 +2690,26 @@ impl From<&str> for Rc<str> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut str> for Rc<str> {
+    /// Allocates a reference-counted string slice and copies `v` into it.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use std::rc::Rc;
+    /// let mut original = String::from("statue");
+    /// let original: &mut str = &mut original;
+    /// let shared: Rc<str> = Rc::from(original);
+    /// assert_eq!("statue", &shared[..]);
+    /// ```
+    #[inline]
+    fn from(v: &mut str) -> Rc<str> {
+        Rc::from(&*v)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "shared_from_slice", since = "1.21.0")]
 impl From<String> for Rc<str> {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 15a1b0f283449..3ace7d1fa0343 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3612,6 +3612,26 @@ impl<T: Clone> From<&[T]> for Arc<[T]> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl<T: Clone> From<&mut [T]> for Arc<[T]> {
+    /// Allocates a reference-counted slice and fills it by cloning `v`'s items.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use std::sync::Arc;
+    /// let mut original = [1, 2, 3];
+    /// let original: &mut [i32] = &mut original;
+    /// let shared: Arc<[i32]> = Arc::from(original);
+    /// assert_eq!(&[1, 2, 3], &shared[..]);
+    /// ```
+    #[inline]
+    fn from(v: &mut [T]) -> Arc<[T]> {
+        Arc::from(&*v)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "shared_from_slice", since = "1.21.0")]
 impl From<&str> for Arc<str> {
@@ -3631,6 +3651,26 @@ impl From<&str> for Arc<str> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut str> for Arc<str> {
+    /// Allocates a reference-counted `str` and copies `v` into it.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use std::sync::Arc;
+    /// let mut original = String::from("eggplant");
+    /// let original: &mut str = &mut original;
+    /// let shared: Arc<str> = Arc::from(original);
+    /// assert_eq!("eggplant", &shared[..]);
+    /// ```
+    #[inline]
+    fn from(v: &mut str) -> Arc<str> {
+        Arc::from(&*v)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "shared_from_slice", since = "1.21.0")]
 impl From<String> for Arc<str> {
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 2243f100643df..b19d482feaad0 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -1225,6 +1225,15 @@ impl From<&OsStr> for Box<OsStr> {
     }
 }
 
+#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut OsStr> for Box<OsStr> {
+    /// Copies the string into a newly allocated <code>[Box]&lt;[OsStr]&gt;</code>.
+    #[inline]
+    fn from(s: &mut OsStr) -> Box<OsStr> {
+        Self::from(&*s)
+    }
+}
+
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, OsStr>> for Box<OsStr> {
     /// Converts a `Cow<'a, OsStr>` into a <code>[Box]&lt;[OsStr]&gt;</code>,
@@ -1296,6 +1305,15 @@ impl From<&OsStr> for Arc<OsStr> {
     }
 }
 
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut OsStr> for Arc<OsStr> {
+    /// Copies the string into a newly allocated <code>[Arc]&lt;[OsStr]&gt;</code>.
+    #[inline]
+    fn from(s: &mut OsStr) -> Arc<OsStr> {
+        Arc::from(&*s)
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
     /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`]
@@ -1317,6 +1335,15 @@ impl From<&OsStr> for Rc<OsStr> {
     }
 }
 
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut OsStr> for Rc<OsStr> {
+    /// Copies the string into a newly allocated <code>[Rc]&lt;[OsStr]&gt;</code>.
+    #[inline]
+    fn from(s: &mut OsStr) -> Rc<OsStr> {
+        Rc::from(&*s)
+    }
+}
+
 #[stable(feature = "cow_from_osstr", since = "1.28.0")]
 impl<'a> From<OsString> for Cow<'a, OsStr> {
     /// Moves the string into a [`Cow::Owned`].
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 62125f885b2ff..5662a44d83232 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1762,6 +1762,16 @@ impl From<&Path> for Box<Path> {
     }
 }
 
+#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut Path> for Box<Path> {
+    /// Creates a boxed [`Path`] from a reference.
+    ///
+    /// This will allocate and clone `path` to it.
+    fn from(path: &mut Path) -> Box<Path> {
+        Self::from(&*path)
+    }
+}
+
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, Path>> for Box<Path> {
     /// Creates a boxed [`Path`] from a clone-on-write pointer.
@@ -1990,6 +2000,15 @@ impl From<&Path> for Arc<Path> {
     }
 }
 
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut Path> for Arc<Path> {
+    /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer.
+    #[inline]
+    fn from(s: &mut Path) -> Arc<Path> {
+        Arc::from(&*s)
+    }
+}
+
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<PathBuf> for Rc<Path> {
     /// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into
@@ -2011,6 +2030,15 @@ impl From<&Path> for Rc<Path> {
     }
 }
 
+#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")]
+impl From<&mut Path> for Rc<Path> {
+    /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer.
+    #[inline]
+    fn from(s: &mut Path) -> Rc<Path> {
+        Rc::from(&*s)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for Path {
     type Owned = PathBuf;