Skip to content

Commit

Permalink
Merge from rustc
Browse files Browse the repository at this point in the history
  • Loading branch information
The Miri Cronjob Bot committed Sep 16, 2024
2 parents f30a0ad + ee67105 commit 2c1bd02
Show file tree
Hide file tree
Showing 20 changed files with 648 additions and 48 deletions.
223 changes: 223 additions & 0 deletions alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,59 @@ impl<T: ?Sized> Box<T> {
pub unsafe fn from_raw(raw: *mut T) -> Self {
unsafe { Self::from_raw_in(raw, Global) }
}

/// Constructs a box from a `NonNull` pointer.
///
/// After calling this function, the `NonNull` pointer is owned by
/// the resulting `Box`. Specifically, the `Box` destructor will call
/// the destructor of `T` and free the allocated memory. For this
/// to be safe, the memory must have been allocated in accordance
/// with the [memory layout] used by `Box` .
///
/// # Safety
///
/// This function is unsafe because improper use may lead to
/// memory problems. For example, a double-free may occur if the
/// function is called twice on the same `NonNull` pointer.
///
/// The safety conditions are described in the [memory layout] section.
///
/// # Examples
///
/// Recreate a `Box` which was previously converted to a `NonNull`
/// pointer using [`Box::into_non_null`]:
/// ```
/// #![feature(box_vec_non_null)]
///
/// let x = Box::new(5);
/// let non_null = Box::into_non_null(x);
/// let x = unsafe { Box::from_non_null(non_null) };
/// ```
/// Manually create a `Box` from scratch by using the global allocator:
/// ```
/// #![feature(box_vec_non_null)]
///
/// use std::alloc::{alloc, Layout};
/// use std::ptr::NonNull;
///
/// unsafe {
/// let non_null = NonNull::new(alloc(Layout::new::<i32>()).cast::<i32>())
/// .expect("allocation failed");
/// // In general .write is required to avoid attempting to destruct
/// // the (uninitialized) previous contents of `non_null`.
/// non_null.write(5);
/// let x = Box::from_non_null(non_null);
/// }
/// ```
///
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
#[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
#[inline]
#[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"]
pub unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
unsafe { Self::from_raw(ptr.as_ptr()) }
}
}

impl<T: ?Sized, A: Allocator> Box<T, A> {
Expand Down Expand Up @@ -1117,6 +1170,61 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
}

/// Constructs a box from a `NonNull` pointer in the given allocator.
///
/// After calling this function, the `NonNull` pointer is owned by
/// the resulting `Box`. Specifically, the `Box` destructor will call
/// the destructor of `T` and free the allocated memory. For this
/// to be safe, the memory must have been allocated in accordance
/// with the [memory layout] used by `Box` .
///
/// # Safety
///
/// This function is unsafe because improper use may lead to
/// memory problems. For example, a double-free may occur if the
/// function is called twice on the same raw pointer.
///
///
/// # Examples
///
/// Recreate a `Box` which was previously converted to a `NonNull` pointer
/// using [`Box::into_non_null_with_allocator`]:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
///
/// use std::alloc::System;
///
/// let x = Box::new_in(5, System);
/// let (non_null, alloc) = Box::into_non_null_with_allocator(x);
/// let x = unsafe { Box::from_non_null_in(non_null, alloc) };
/// ```
/// Manually create a `Box` from scratch by using the system allocator:
/// ```
/// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)]
///
/// use std::alloc::{Allocator, Layout, System};
///
/// unsafe {
/// let non_null = System.allocate(Layout::new::<i32>())?.cast::<i32>();
/// // In general .write is required to avoid attempting to destruct
/// // the (uninitialized) previous contents of `non_null`.
/// non_null.write(5);
/// let x = Box::from_non_null_in(non_null, System);
/// }
/// # Ok::<(), std::alloc::AllocError>(())
/// ```
///
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline]
pub const unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self {
// SAFETY: guaranteed by the caller.
unsafe { Box::from_raw_in(raw.as_ptr(), alloc) }
}

/// Consumes the `Box`, returning a wrapped raw pointer.
///
/// The pointer will be properly aligned and non-null.
Expand Down Expand Up @@ -1172,6 +1280,66 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
unsafe { addr_of_mut!(*&mut *Self::into_raw_with_allocator(b).0) }
}

/// Consumes the `Box`, returning a wrapped `NonNull` pointer.
///
/// The pointer will be properly aligned.
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory, taking
/// into account the [memory layout] used by `Box`. The easiest way to
/// do this is to convert the `NonNull` pointer back into a `Box` with the
/// [`Box::from_non_null`] function, allowing the `Box` destructor to
/// perform the cleanup.
///
/// Note: this is an associated function, which means that you have
/// to call it as `Box::into_non_null(b)` instead of `b.into_non_null()`.
/// This is so that there is no conflict with a method on the inner type.
///
/// # Examples
/// Converting the `NonNull` pointer back into a `Box` with [`Box::from_non_null`]
/// for automatic cleanup:
/// ```
/// #![feature(box_vec_non_null)]
///
/// let x = Box::new(String::from("Hello"));
/// let non_null = Box::into_non_null(x);
/// let x = unsafe { Box::from_non_null(non_null) };
/// ```
/// Manual cleanup by explicitly running the destructor and deallocating
/// the memory:
/// ```
/// #![feature(box_vec_non_null)]
///
/// use std::alloc::{dealloc, Layout};
///
/// let x = Box::new(String::from("Hello"));
/// let non_null = Box::into_non_null(x);
/// unsafe {
/// non_null.drop_in_place();
/// dealloc(non_null.as_ptr().cast::<u8>(), Layout::new::<String>());
/// }
/// ```
/// Note: This is equivalent to the following:
/// ```
/// #![feature(box_vec_non_null)]
///
/// let x = Box::new(String::from("Hello"));
/// let non_null = Box::into_non_null(x);
/// unsafe {
/// drop(Box::from_non_null(non_null));
/// }
/// ```
///
/// [memory layout]: self#memory-layout
#[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
#[inline]
pub fn into_non_null(b: Self) -> NonNull<T> {
// SAFETY: `Box` is guaranteed to be non-null.
unsafe { NonNull::new_unchecked(Self::into_raw(b)) }
}

/// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
///
/// The pointer will be properly aligned and non-null.
Expand Down Expand Up @@ -1233,6 +1401,61 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
(ptr, alloc)
}

/// Consumes the `Box`, returning a wrapped `NonNull` pointer and the allocator.
///
/// The pointer will be properly aligned.
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory, taking
/// into account the [memory layout] used by `Box`. The easiest way to
/// do this is to convert the `NonNull` pointer back into a `Box` with the
/// [`Box::from_non_null_in`] function, allowing the `Box` destructor to
/// perform the cleanup.
///
/// Note: this is an associated function, which means that you have
/// to call it as `Box::into_non_null_with_allocator(b)` instead of
/// `b.into_non_null_with_allocator()`. This is so that there is no
/// conflict with a method on the inner type.
///
/// # Examples
/// Converting the `NonNull` pointer back into a `Box` with
/// [`Box::from_non_null_in`] for automatic cleanup:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
///
/// use std::alloc::System;
///
/// let x = Box::new_in(String::from("Hello"), System);
/// let (non_null, alloc) = Box::into_non_null_with_allocator(x);
/// let x = unsafe { Box::from_non_null_in(non_null, alloc) };
/// ```
/// Manual cleanup by explicitly running the destructor and deallocating
/// the memory:
/// ```
/// #![feature(allocator_api, box_vec_non_null)]
///
/// use std::alloc::{Allocator, Layout, System};
///
/// let x = Box::new_in(String::from("Hello"), System);
/// let (non_null, alloc) = Box::into_non_null_with_allocator(x);
/// unsafe {
/// non_null.drop_in_place();
/// alloc.deallocate(non_null.cast::<u8>(), Layout::new::<String>());
/// }
/// ```
///
/// [memory layout]: self#memory-layout
#[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
#[inline]
pub fn into_non_null_with_allocator(b: Self) -> (NonNull<T>, A) {
let (ptr, alloc) = Box::into_raw_with_allocator(b);
// SAFETY: `Box` is guaranteed to be non-null.
unsafe { (NonNull::new_unchecked(ptr), alloc) }
}

#[unstable(
feature = "ptr_internals",
issue = "none",
Expand Down
4 changes: 2 additions & 2 deletions alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
#![feature(const_maybe_uninit_write)]
#![feature(const_option)]
#![feature(const_pin)]
#![feature(const_refs_to_cell)]
#![feature(const_size_of_val)]
#![feature(core_intrinsics)]
#![feature(deprecated_suggestion)]
Expand Down Expand Up @@ -164,13 +163,14 @@
//
// Language features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(const_mut_refs))]
#![cfg_attr(bootstrap, feature(const_refs_to_cell))]
#![cfg_attr(not(test), feature(coroutine_trait))]
#![cfg_attr(test, feature(panic_update_hook))]
#![cfg_attr(test, feature(test))]
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(cfg_sanitize)]
#![feature(const_mut_refs)]
#![feature(const_precise_live_drops)]
#![feature(const_ptr_write)]
#![feature(const_try)]
Expand Down
74 changes: 74 additions & 0 deletions alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,56 @@ impl String {
Cow::Owned(res)
}

/// Converts a [`Vec<u8>`] to a `String`, substituting invalid UTF-8
/// sequences with replacement characters.
///
/// See [`from_utf8_lossy`] for more details.
///
/// [`from_utf8_lossy`]: String::from_utf8_lossy
///
/// Note that this function does not guarantee reuse of the original `Vec`
/// allocation.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(string_from_utf8_lossy_owned)]
/// // some bytes, in a vector
/// let sparkle_heart = vec![240, 159, 146, 150];
///
/// let sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart);
///
/// assert_eq!(String::from("💖"), sparkle_heart);
/// ```
///
/// Incorrect bytes:
///
/// ```
/// #![feature(string_from_utf8_lossy_owned)]
/// // some invalid bytes
/// let input: Vec<u8> = b"Hello \xF0\x90\x80World".into();
/// let output = String::from_utf8_lossy_owned(input);
///
/// assert_eq!(String::from("Hello �World"), output);
/// ```
#[must_use]
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")]
pub fn from_utf8_lossy_owned(v: Vec<u8>) -> String {
if let Cow::Owned(string) = String::from_utf8_lossy(&v) {
string
} else {
// SAFETY: `String::from_utf8_lossy`'s contract ensures that if
// it returns a `Cow::Borrowed`, it is a valid UTF-8 string.
// Otherwise, it returns a new allocation of an owned `String`, with
// replacement characters for invalid sequences, which is returned
// above.
unsafe { String::from_utf8_unchecked(v) }
}
}

/// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`]
/// if `v` contains any invalid data.
///
Expand Down Expand Up @@ -2010,6 +2060,30 @@ impl FromUtf8Error {
&self.bytes[..]
}

/// Converts the bytes into a `String` lossily, substituting invalid UTF-8
/// sequences with replacement characters.
///
/// See [`String::from_utf8_lossy`] for more details on replacement of
/// invalid sequences, and [`String::from_utf8_lossy_owned`] for the
/// `String` function which corresponds to this function.
///
/// # Examples
///
/// ```
/// #![feature(string_from_utf8_lossy_owned)]
/// // some invalid bytes
/// let input: Vec<u8> = b"Hello \xF0\x90\x80World".into();
/// let output = String::from_utf8(input).unwrap_or_else(|e| e.into_utf8_lossy());
///
/// assert_eq!(String::from("Hello �World"), output);
/// ```
#[must_use]
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")]
pub fn into_utf8_lossy(self) -> String {
String::from_utf8_lossy_owned(self.bytes)
}

/// Returns the bytes that were attempted to convert to a `String`.
///
/// This method is carefully constructed to avoid allocation. It will
Expand Down
2 changes: 1 addition & 1 deletion alloc/src/vec/in_place_collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ where

mem::forget(dst_guard);

let vec = unsafe { Vec::from_nonnull(dst_buf, len, dst_cap) };
let vec = unsafe { Vec::from_parts(dst_buf, len, dst_cap) };

vec
}
Expand Down
Loading

0 comments on commit 2c1bd02

Please sign in to comment.