Add Box::(try_)clone_from_ref(_in)
This commit is contained in:
parent
07bdbaedc6
commit
9e497b6071
5 changed files with 130 additions and 8 deletions
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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> {};
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue