Auto merge of #149079 - zachs18:clone_from_ref, r=Mark-Simulacrum

Add `Box::clone_from_ref` and similar under `feature(clone_from_ref)`

Tracking issue: https://github.com/rust-lang/rust/issues/149075

Accepted ACP: https://github.com/rust-lang/libs-team/issues/483

This PR implements `clone_from_ref` (and `try_*` and `_*in` variants), to get a `Box<T>`, `Arc<T>`, or `Rc<T>` by cloning from a `&T` where `T: CloneToUninit`.

The "Implement..." commits replace some ad-hoc conversions with `clone_from_ref` variants, which can be split out to a separate PR if desired.

This PR will conflict with https://github.com/rust-lang/rust/pull/148769 due to usage of `Layout::dangling` (which that PR is renaming to `dangling_ptr`), so they should not be rolled up together, and the one which merges later will need to be amended.
This commit is contained in:
bors 2025-11-26 18:21:00 +00:00
commit 1be6b13be7
13 changed files with 368 additions and 104 deletions

View file

@ -184,7 +184,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::borrow::{Borrow, BorrowMut};
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::cmp::Ordering;
use core::error::{self, Error};
@ -733,6 +732,128 @@ impl<T, A: Allocator> Box<T, A> {
}
}
impl<T: ?Sized + CloneToUninit> Box<T> {
/// Allocates memory on the heap then clones `src` into it.
///
/// This doesn't actually allocate if `src` is zero-sized.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
///
/// let hello: Box<str> = Box::clone_from_ref("hello");
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
#[must_use]
#[inline]
pub fn clone_from_ref(src: &T) -> Box<T> {
Box::clone_from_ref_in(src, Global)
}
/// Allocates memory on the heap then clones `src` into it, returning an error if allocation fails.
///
/// This doesn't actually allocate if `src` is zero-sized.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
///
/// let hello: Box<str> = Box::try_clone_from_ref("hello")?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
#[must_use]
#[inline]
pub fn try_clone_from_ref(src: &T) -> Result<Box<T>, AllocError> {
Box::try_clone_from_ref_in(src, Global)
}
}
impl<T: ?Sized + CloneToUninit, A: Allocator> Box<T, A> {
/// Allocates memory in the given allocator then clones `src` into it.
///
/// This doesn't actually allocate if `src` is zero-sized.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///
/// let hello: Box<str, System> = Box::clone_from_ref_in("hello", System);
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
#[must_use]
#[inline]
pub fn clone_from_ref_in(src: &T, alloc: A) -> Box<T, A> {
let layout = Layout::for_value::<T>(src);
match Box::try_clone_from_ref_in(src, alloc) {
Ok(bx) => bx,
Err(_) => handle_alloc_error(layout),
}
}
/// Allocates memory in the given allocator then clones `src` into it, returning an error if allocation fails.
///
/// This doesn't actually allocate if `src` is zero-sized.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
///
/// use std::alloc::System;
///
/// let hello: Box<str, System> = Box::try_clone_from_ref_in("hello", System)?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
#[must_use]
#[inline]
pub fn try_clone_from_ref_in(src: &T, alloc: A) -> Result<Box<T, A>, AllocError> {
struct DeallocDropGuard<'a, A: Allocator>(Layout, &'a A, NonNull<u8>);
impl<'a, A: Allocator> Drop for DeallocDropGuard<'a, A> {
fn drop(&mut self) {
let &mut DeallocDropGuard(layout, alloc, ptr) = self;
// Safety: `ptr` was allocated by `*alloc` with layout `layout`
unsafe {
alloc.deallocate(ptr, layout);
}
}
}
let layout = Layout::for_value::<T>(src);
let (ptr, guard) = if layout.size() == 0 {
(layout.dangling(), None)
} else {
// Safety: layout is non-zero-sized
let ptr = alloc.allocate(layout)?.cast();
(ptr, Some(DeallocDropGuard(layout, &alloc, ptr)))
};
let ptr = ptr.as_ptr();
// Safety: `*ptr` is newly allocated, correctly aligned to `align_of_val(src)`,
// and is valid for writes for `size_of_val(src)`.
// If this panics, then `guard` will deallocate for us (if allocation occuured)
unsafe {
<T as CloneToUninit>::clone_to_uninit(src, ptr);
}
// Defuse the deallocate guard
core::mem::forget(guard);
// Safety: We just initialized `*ptr` as a clone of `src`
Ok(unsafe { Box::from_raw_in(ptr.with_metadata_of(src), alloc) })
}
}
impl<T> Box<[T]> {
/// Constructs a new boxed slice with uninitialized contents.
///

View file

@ -1,21 +1,15 @@
use core::any::Any;
#[cfg(not(no_global_oom_handling))]
use core::clone::TrivialClone;
use core::error::Error;
#[cfg(not(no_global_oom_handling))]
use core::fmt;
use core::mem;
use core::pin::Pin;
#[cfg(not(no_global_oom_handling))]
use core::{fmt, ptr};
use crate::alloc::Allocator;
#[cfg(not(no_global_oom_handling))]
use crate::borrow::Cow;
use crate::boxed::Box;
#[cfg(not(no_global_oom_handling))]
use crate::raw_vec::RawVec;
#[cfg(not(no_global_oom_handling))]
use crate::str::from_boxed_utf8_unchecked;
#[cfg(not(no_global_oom_handling))]
use crate::string::String;
#[cfg(not(no_global_oom_handling))]
use crate::vec::Vec;
@ -62,35 +56,6 @@ where
}
}
/// Specialization trait used for `From<&[T]>`.
#[cfg(not(no_global_oom_handling))]
trait BoxFromSlice<T> {
fn from_slice(slice: &[T]) -> Self;
}
#[cfg(not(no_global_oom_handling))]
impl<T: Clone> BoxFromSlice<T> for Box<[T]> {
#[inline]
default fn from_slice(slice: &[T]) -> Self {
slice.to_vec().into_boxed_slice()
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: TrivialClone> BoxFromSlice<T> for Box<[T]> {
#[inline]
fn from_slice(slice: &[T]) -> Self {
let len = slice.len();
let buf = RawVec::with_capacity(len);
// SAFETY: since `T` implements `TrivialClone`, this is sound and
// equivalent to the above.
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box(slice.len()).assume_init()
}
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_from_slice", since = "1.17.0")]
impl<T: Clone> From<&[T]> for Box<[T]> {
@ -109,7 +74,7 @@ impl<T: Clone> From<&[T]> for Box<[T]> {
/// ```
#[inline]
fn from(slice: &[T]) -> Box<[T]> {
<Self as BoxFromSlice<T>>::from_slice(slice)
Box::clone_from_ref(slice)
}
}
@ -170,7 +135,7 @@ impl From<&str> for Box<str> {
/// ```
#[inline]
fn from(s: &str) -> Box<str> {
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
Box::clone_from_ref(s)
}
}

View file

@ -766,8 +766,7 @@ impl From<&CStr> for Box<CStr> {
/// Converts a `&CStr` into a `Box<CStr>`,
/// by copying the contents into a newly allocated [`Box`].
fn from(s: &CStr) -> Box<CStr> {
let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
Box::clone_from_ref(s)
}
}

View file

@ -243,9 +243,9 @@
use core::any::Any;
use core::cell::{Cell, CloneFromCell};
use core::clone::UseCloned;
#[cfg(not(no_global_oom_handling))]
use core::clone::{CloneToUninit, TrivialClone};
use core::clone::TrivialClone;
use core::clone::{CloneToUninit, UseCloned};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
@ -1290,6 +1290,104 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
}
}
impl<T: ?Sized + CloneToUninit> Rc<T> {
/// Constructs a new `Rc<T>` with a clone of `value`.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// use std::rc::Rc;
///
/// let hello: Rc<str> = Rc::clone_from_ref("hello");
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
pub fn clone_from_ref(value: &T) -> Rc<T> {
Rc::clone_from_ref_in(value, Global)
}
/// Constructs a new `Rc<T>` with a clone of `value`, returning an error if allocation fails
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::rc::Rc;
///
/// let hello: Rc<str> = Rc::try_clone_from_ref("hello")?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn try_clone_from_ref(value: &T) -> Result<Rc<T>, AllocError> {
Rc::try_clone_from_ref_in(value, Global)
}
}
impl<T: ?Sized + CloneToUninit, A: Allocator> Rc<T, A> {
/// Constructs a new `Rc<T>` with a clone of `value` in the provided allocator.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::rc::Rc;
/// use std::alloc::System;
///
/// let hello: Rc<str, System> = Rc::clone_from_ref_in("hello", System);
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn clone_from_ref_in(value: &T, alloc: A) -> Rc<T, A> {
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueRcUninit<T, A> = UniqueRcUninit::new(value, alloc);
// Initialize with clone of value.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
value.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_rc()
};
initialized_clone
}
/// Constructs a new `Rc<T>` with a clone of `value` in the provided allocator, returning an error if allocation fails
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::rc::Rc;
/// use std::alloc::System;
///
/// let hello: Rc<str, System> = Rc::try_clone_from_ref_in("hello", System)?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result<Rc<T, A>, AllocError> {
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueRcUninit<T, A> = UniqueRcUninit::try_new(value, alloc)?;
// Initialize with clone of value.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
value.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_rc()
};
Ok(initialized_clone)
}
}
impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> {
/// Converts to `Rc<[T]>`.
///
@ -1969,22 +2067,7 @@ impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Rc<T, A> {
if Rc::strong_count(this) != 1 {
// Gotta clone the data, there are other Rcs.
let this_data_ref: &T = &**this;
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueRcUninit<T, A> =
UniqueRcUninit::new(this_data_ref, this.alloc.clone());
// Initialize with clone of this.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_rc()
};
// Replace `this` with newly constructed Rc.
*this = initialized_clone;
*this = Rc::clone_from_ref_in(&**this, this.alloc.clone());
} else if Rc::weak_count(this) != 0 {
// Can just steal the data, all that's left is Weaks
@ -4358,16 +4441,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
/// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic.
/// It is nearly a duplicate of `UniqueRc<MaybeUninit<T>, A>` except that it allows `T: !Sized`,
/// which `MaybeUninit` does not.
#[cfg(not(no_global_oom_handling))]
struct UniqueRcUninit<T: ?Sized, A: Allocator> {
ptr: NonNull<RcInner<T>>,
layout_for_value: Layout,
alloc: Option<A>,
}
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
/// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it.
#[cfg(not(no_global_oom_handling))]
fn new(for_value: &T, alloc: A) -> UniqueRcUninit<T, A> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
@ -4380,6 +4462,20 @@ impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }
}
/// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it,
/// returning an error if allocation fails.
fn try_new(for_value: &T, alloc: A) -> Result<UniqueRcUninit<T, A>, AllocError> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
Rc::try_allocate_for_layout(
layout,
|layout_for_rc_inner| alloc.allocate(layout_for_rc_inner),
|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcInner<T>),
)?
};
Ok(Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) })
}
/// Returns the pointer to be written into to initialize the [`Rc`].
fn data_ptr(&mut self) -> *mut T {
let offset = data_offset_align(self.layout_for_value.align());
@ -4402,7 +4498,6 @@ impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
}
}
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> Drop for UniqueRcUninit<T, A> {
fn drop(&mut self) {
// SAFETY:

View file

@ -11,10 +11,8 @@
use core::any::Any;
use core::cell::CloneFromCell;
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
#[cfg(not(no_global_oom_handling))]
use core::clone::TrivialClone;
use core::clone::UseCloned;
use core::clone::{CloneToUninit, UseCloned};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
@ -1442,6 +1440,104 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
}
}
impl<T: ?Sized + CloneToUninit> Arc<T> {
/// Constructs a new `Arc<T>` with a clone of `value`.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// use std::sync::Arc;
///
/// let hello: Arc<str> = Arc::clone_from_ref("hello");
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
pub fn clone_from_ref(value: &T) -> Arc<T> {
Arc::clone_from_ref_in(value, Global)
}
/// Constructs a new `Arc<T>` with a clone of `value`, returning an error if allocation fails
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::sync::Arc;
///
/// let hello: Arc<str> = Arc::try_clone_from_ref("hello")?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn try_clone_from_ref(value: &T) -> Result<Arc<T>, AllocError> {
Arc::try_clone_from_ref_in(value, Global)
}
}
impl<T: ?Sized + CloneToUninit, A: Allocator> Arc<T, A> {
/// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator.
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::sync::Arc;
/// use std::alloc::System;
///
/// let hello: Arc<str, System> = Arc::clone_from_ref_in("hello", System);
/// ```
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn clone_from_ref_in(value: &T, alloc: A) -> Arc<T, A> {
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueArcUninit<T, A> = UniqueArcUninit::new(value, alloc);
// Initialize with clone of value.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
value.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_arc()
};
initialized_clone
}
/// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator, returning an error if allocation fails
///
/// # Examples
///
/// ```
/// #![feature(clone_from_ref)]
/// #![feature(allocator_api)]
/// use std::sync::Arc;
/// use std::alloc::System;
///
/// let hello: Arc<str, System> = Arc::try_clone_from_ref_in("hello", System)?;
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
#[unstable(feature = "clone_from_ref", issue = "149075")]
//#[unstable(feature = "allocator_api", issue = "32838")]
pub fn try_clone_from_ref_in(value: &T, alloc: A) -> Result<Arc<T, A>, AllocError> {
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueArcUninit<T, A> = UniqueArcUninit::try_new(value, alloc)?;
// Initialize with clone of value.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
value.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_arc()
};
Ok(initialized_clone)
}
}
impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
/// Converts to `Arc<[T]>`.
///
@ -2406,19 +2502,7 @@ impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Arc<T, A> {
// deallocated.
if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() {
// Another strong pointer exists, so we must clone.
let this_data_ref: &T = &**this;
// `in_progress` drops the allocation if we panic before finishing initializing it.
let mut in_progress: UniqueArcUninit<T, A> =
UniqueArcUninit::new(this_data_ref, this.alloc.clone());
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_arc()
};
*this = initialized_clone;
*this = Arc::clone_from_ref_in(&**this, this.alloc.clone());
} else if this.inner().weak.load(Relaxed) != 1 {
// Relaxed suffices in the above because this is fundamentally an
// optimization: we are always racing with weak pointers being
@ -4137,16 +4221,15 @@ fn data_offset_align(align: usize) -> usize {
/// but will deallocate it (without dropping the value) when dropped.
///
/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic.
#[cfg(not(no_global_oom_handling))]
struct UniqueArcUninit<T: ?Sized, A: Allocator> {
ptr: NonNull<ArcInner<T>>,
layout_for_value: Layout,
alloc: Option<A>,
}
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
/// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it.
#[cfg(not(no_global_oom_handling))]
fn new(for_value: &T, alloc: A) -> UniqueArcUninit<T, A> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
@ -4159,6 +4242,20 @@ impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }
}
/// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it,
/// returning an error if allocation fails.
fn try_new(for_value: &T, alloc: A) -> Result<UniqueArcUninit<T, A>, AllocError> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
Arc::try_allocate_for_layout(
layout,
|layout_for_arcinner| alloc.allocate(layout_for_arcinner),
|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const ArcInner<T>),
)?
};
Ok(Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) })
}
/// Returns the pointer to be written into to initialize the [`Arc`].
fn data_ptr(&mut self) -> *mut T {
let offset = data_offset_align(self.layout_for_value.align());

View file

@ -1285,8 +1285,7 @@ impl From<&OsStr> for Box<OsStr> {
/// Copies the string into a newly allocated <code>[Box]&lt;[OsStr]&gt;</code>.
#[inline]
fn from(s: &OsStr) -> Box<OsStr> {
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
Box::clone_from_ref(s)
}
}

View file

@ -374,6 +374,7 @@
// tidy-alphabetical-start
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(clone_from_ref)]
#![feature(get_mut_unchecked)]
#![feature(map_try_insert)]
#![feature(slice_concat_trait)]

View file

@ -1877,9 +1877,7 @@ impl From<&Path> for Box<Path> {
///
/// This will allocate and clone `path` to it.
fn from(path: &Path) -> Box<Path> {
let boxed: Box<OsStr> = path.inner.into();
let rw = Box::into_raw(boxed) as *mut Path;
unsafe { Box::from_raw(rw) }
Box::clone_from_ref(path)
}
}

View file

@ -321,12 +321,6 @@ impl Slice {
self.inner.clone_into(&mut buf.inner)
}
#[inline]
pub fn into_box(&self) -> Box<Slice> {
let boxed: Box<[u8]> = self.inner.into();
unsafe { mem::transmute(boxed) }
}
#[inline]
pub fn empty_box() -> Box<Slice> {
let boxed: Box<[u8]> = Default::default();

View file

@ -271,11 +271,6 @@ impl Slice {
self.inner.clone_into(&mut buf.inner)
}
#[inline]
pub fn into_box(&self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_box()) }
}
#[inline]
pub fn empty_box() -> Box<Slice> {
unsafe { mem::transmute(Wtf8::empty_box()) }

View file

@ -63,7 +63,7 @@ LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
|
= and 13 other candidates
= and 15 other candidates
help: consider using the `Default` trait
|
LL - wtf: Some(Box(U {
@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
|
= and 14 other candidates
= and 16 other candidates
help: consider using the `Default` trait
|
LL - let _ = Box {};
@ -146,7 +146,7 @@ LL + let _ = Box::<i32>::map(_, _);
LL - let _ = Box::<i32> {};
LL + let _ = Box::<i32>::into_inner(_);
|
= and 5 other candidates
= and 7 other candidates
help: consider using the `Default` trait
|
LL - let _ = Box::<i32> {};

View file

@ -63,7 +63,7 @@ LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
|
= and 13 other candidates
= and 15 other candidates
help: consider using the `Default` trait
|
LL - wtf: Some(Box(U {
@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
|
= and 14 other candidates
= and 16 other candidates
help: consider using the `Default` trait
|
LL - let _ = Box {};

View file

@ -63,7 +63,7 @@ LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
╰ and 13 other candidates
╰ and 15 other candidates
help: consider using the `Default` trait
╭╴
LL - wtf: Some(Box(U {
@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
╰ and 14 other candidates
╰ and 16 other candidates
help: consider using the `Default` trait
╭╴
LL - let _ = Box {};