about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-09-15 05:15:25 +0000
committerbors <bors@rust-lang.org>2024-09-15 05:15:25 +0000
commitbc486f31a69f817ebdef82a968ef6a0db6d3a4fc (patch)
tree603e0fea0c3687452acf66002e6e78be148c95ad
parent4f1be92153167dfc2a54215bfd49f398c04ce647 (diff)
parent4b6f838e5638fe34c056e6f5948edb42b59dd3bc (diff)
downloadrust-bc486f31a69f817ebdef82a968ef6a0db6d3a4fc.tar.gz
rust-bc486f31a69f817ebdef82a968ef6a0db6d3a4fc.zip
Auto merge of #130379 - Zalathar:rollup-wpmcnql, r=Zalathar
Rollup of 6 pull requests

Successful merges:

 - #130042 (properly handle EOF in BufReader::peek)
 - #130061 (Add `NonNull` convenience methods to `Box` and `Vec`)
 - #130202 (set `download-ci-llvm = true` by default on "library" and "tools" profiles)
 - #130214 (MaybeUninit::zeroed: mention that padding is not zeroed)
 - #130353 (Make some lint doctests compatible with `--stage=0`)
 - #130370 (unstable-book: `trait_upcasting` example should not have `#![allow(incomplete_features)]`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--library/alloc/src/boxed.rs223
-rw-r--r--library/alloc/src/vec/in_place_collect.rs2
-rw-r--r--library/alloc/src/vec/mod.rs320
-rw-r--r--library/alloc/src/vec/spec_from_iter.rs2
-rw-r--r--library/core/src/mem/maybe_uninit.rs3
-rw-r--r--library/std/src/io/buffered/bufreader.rs12
-rw-r--r--library/std/src/io/buffered/bufreader/buffer.rs4
-rw-r--r--src/bootstrap/defaults/config.library.toml3
-rw-r--r--src/bootstrap/defaults/config.tools.toml3
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/doc/unstable-book/src/language-features/trait-upcasting.md1
-rw-r--r--tests/ui/privacy/suggest-box-new.stderr4
-rw-r--r--tests/ui/suggestions/deref-path-method.stderr2
-rw-r--r--tests/ui/ufcs/bad-builder.stderr2
16 files changed, 561 insertions, 28 deletions
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index 5b65541bea6..7138d40a48f 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -24,7 +24,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,edition2021
-    /// #![feature(if_let_rescope)]
+    /// #![cfg_attr(not(bootstrap), feature(if_let_rescope))] // Simplify this in bootstrap bump.
     /// #![warn(if_let_rescope)]
     /// #![allow(unused_variables)]
     ///
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f42f35c594b..9b6d63c2ef4 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1870,6 +1870,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,compile_fail
+    /// # #[cfg_attr(bootstrap)] compile_error!(); // Remove this in bootstrap bump.
     /// #![deny(elided_named_lifetimes)]
     /// struct Foo;
     /// impl Foo {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 4b1d493113c..5978908e8f5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -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> {
@@ -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.
@@ -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.
@@ -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",
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index cda63da0904..23dbc3b63f9 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -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
 }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ff084edba8d..2afb5dd0d1a 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -603,15 +603,116 @@ impl<T> Vec<T> {
         unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) }
     }
 
-    /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts`].
+    #[doc(alias = "from_non_null_parts")]
+    /// Creates a `Vec<T>` directly from a `NonNull` pointer, a length, and a capacity.
     ///
     /// # Safety
     ///
-    /// See [`Vec::from_raw_parts`].
+    /// This is highly unsafe, due to the number of invariants that aren't
+    /// checked:
+    ///
+    /// * `ptr` must have been allocated using the global allocator, such as via
+    ///   the [`alloc::alloc`] function.
+    /// * `T` needs to have the same alignment as what `ptr` was allocated with.
+    ///   (`T` having a less strict alignment is not sufficient, the alignment really
+    ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
+    ///   allocated and deallocated with the same layout.)
+    /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
+    ///   to be the same size as the pointer was allocated with. (Because similar to
+    ///   alignment, [`dealloc`] must be called with the same layout `size`.)
+    /// * `length` needs to be less than or equal to `capacity`.
+    /// * The first `length` values must be properly initialized values of type `T`.
+    /// * `capacity` needs to be the capacity that the pointer was allocated with.
+    /// * The allocated size in bytes must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// These requirements are always upheld by any `ptr` that has been allocated
+    /// via `Vec<T>`. Other allocation sources are allowed if the invariants are
+    /// upheld.
+    ///
+    /// Violating these may cause problems like corrupting the allocator's
+    /// internal data structures. For example it is normally **not** safe
+    /// to build a `Vec<u8>` from a pointer to a C `char` array with length
+    /// `size_t`, doing so is only safe if the array was initially allocated by
+    /// a `Vec` or `String`.
+    /// It's also not safe to build one from a `Vec<u16>` and its length, because
+    /// the allocator cares about the alignment, and these two types have different
+    /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
+    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
+    /// these issues, it is often preferable to do casting/transmuting using
+    /// [`NonNull::slice_from_raw_parts`] instead.
+    ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `Vec<T>` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
+    /// [`String`]: crate::string::String
+    /// [`alloc::alloc`]: crate::alloc::alloc
+    /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(box_vec_non_null)]
+    ///
+    /// use std::ptr::NonNull;
+    /// use std::mem;
+    ///
+    /// let v = vec![1, 2, 3];
+    ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
+    /// // Prevent running `v`'s destructor so we are in complete control
+    /// // of the allocation.
+    /// let mut v = mem::ManuallyDrop::new(v);
+    ///
+    /// // Pull out the various important pieces of information about `v`
+    /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) };
+    /// let len = v.len();
+    /// let cap = v.capacity();
+    ///
+    /// unsafe {
+    ///     // Overwrite memory with 4, 5, 6
+    ///     for i in 0..len {
+    ///         p.add(i).write(4 + i);
+    ///     }
+    ///
+    ///     // Put everything back together into a Vec
+    ///     let rebuilt = Vec::from_parts(p, len, cap);
+    ///     assert_eq!(rebuilt, [4, 5, 6]);
+    /// }
+    /// ```
+    ///
+    /// Using memory that was allocated elsewhere:
+    ///
+    /// ```rust
+    /// #![feature(box_vec_non_null)]
+    ///
+    /// use std::alloc::{alloc, Layout};
+    /// use std::ptr::NonNull;
+    ///
+    /// fn main() {
+    ///     let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
+    ///
+    ///     let vec = unsafe {
+    ///         let Some(mem) = NonNull::new(alloc(layout).cast::<u32>()) else {
+    ///             return;
+    ///         };
+    ///
+    ///         mem.write(1_000_000);
+    ///
+    ///         Vec::from_parts(mem, 1, 16)
+    ///     };
+    ///
+    ///     assert_eq!(vec, &[1_000_000]);
+    ///     assert_eq!(vec.capacity(), 16);
+    /// }
+    /// ```
     #[inline]
-    #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling
-    pub(crate) unsafe fn from_nonnull(ptr: NonNull<T>, length: usize, capacity: usize) -> Self {
-        unsafe { Self::from_nonnull_in(ptr, length, capacity, Global) }
+    #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
+    pub unsafe fn from_parts(ptr: NonNull<T>, length: usize, capacity: usize) -> Self {
+        unsafe { Self::from_parts_in(ptr, length, capacity, Global) }
     }
 }
 
@@ -830,19 +931,119 @@ impl<T, A: Allocator> Vec<T, A> {
         unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } }
     }
 
-    /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts_in`].
+    #[doc(alias = "from_non_null_parts_in")]
+    /// Creates a `Vec<T, A>` directly from a `NonNull` pointer, a length, a capacity,
+    /// and an allocator.
     ///
     /// # Safety
     ///
-    /// See [`Vec::from_raw_parts_in`].
+    /// This is highly unsafe, due to the number of invariants that aren't
+    /// checked:
+    ///
+    /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`.
+    /// * `T` needs to have the same alignment as what `ptr` was allocated with.
+    ///   (`T` having a less strict alignment is not sufficient, the alignment really
+    ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
+    ///   allocated and deallocated with the same layout.)
+    /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
+    ///   to be the same size as the pointer was allocated with. (Because similar to
+    ///   alignment, [`dealloc`] must be called with the same layout `size`.)
+    /// * `length` needs to be less than or equal to `capacity`.
+    /// * The first `length` values must be properly initialized values of type `T`.
+    /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
+    /// * The allocated size in bytes must be no larger than `isize::MAX`.
+    ///   See the safety documentation of [`pointer::offset`].
+    ///
+    /// These requirements are always upheld by any `ptr` that has been allocated
+    /// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
+    /// upheld.
+    ///
+    /// Violating these may cause problems like corrupting the allocator's
+    /// internal data structures. For example it is **not** safe
+    /// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
+    /// It's also not safe to build one from a `Vec<u16>` and its length, because
+    /// the allocator cares about the alignment, and these two types have different
+    /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
+    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
+    ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `Vec<T>` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
+    /// [`String`]: crate::string::String
+    /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
+    /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory
+    /// [*fit*]: crate::alloc::Allocator#memory-fitting
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, box_vec_non_null)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// use std::ptr::NonNull;
+    /// use std::mem;
+    ///
+    /// let mut v = Vec::with_capacity_in(3, System);
+    /// v.push(1);
+    /// v.push(2);
+    /// v.push(3);
+    ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
+    /// // Prevent running `v`'s destructor so we are in complete control
+    /// // of the allocation.
+    /// let mut v = mem::ManuallyDrop::new(v);
+    ///
+    /// // Pull out the various important pieces of information about `v`
+    /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) };
+    /// let len = v.len();
+    /// let cap = v.capacity();
+    /// let alloc = v.allocator();
+    ///
+    /// unsafe {
+    ///     // Overwrite memory with 4, 5, 6
+    ///     for i in 0..len {
+    ///         p.add(i).write(4 + i);
+    ///     }
+    ///
+    ///     // Put everything back together into a Vec
+    ///     let rebuilt = Vec::from_parts_in(p, len, cap, alloc.clone());
+    ///     assert_eq!(rebuilt, [4, 5, 6]);
+    /// }
+    /// ```
+    ///
+    /// Using memory that was allocated elsewhere:
+    ///
+    /// ```rust
+    /// #![feature(allocator_api, box_vec_non_null)]
+    ///
+    /// use std::alloc::{AllocError, Allocator, Global, Layout};
+    ///
+    /// fn main() {
+    ///     let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
+    ///
+    ///     let vec = unsafe {
+    ///         let mem = match Global.allocate(layout) {
+    ///             Ok(mem) => mem.cast::<u32>(),
+    ///             Err(AllocError) => return,
+    ///         };
+    ///
+    ///         mem.write(1_000_000);
+    ///
+    ///         Vec::from_parts_in(mem, 1, 16, Global)
+    ///     };
+    ///
+    ///     assert_eq!(vec, &[1_000_000]);
+    ///     assert_eq!(vec.capacity(), 16);
+    /// }
+    /// ```
     #[inline]
-    #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling
-    pub(crate) unsafe fn from_nonnull_in(
-        ptr: NonNull<T>,
-        length: usize,
-        capacity: usize,
-        alloc: A,
-    ) -> Self {
+    #[unstable(feature = "allocator_api", reason = "new API", issue = "32838")]
+    // #[unstable(feature = "box_vec_non_null", issue = "130364")]
+    pub unsafe fn from_parts_in(ptr: NonNull<T>, length: usize, capacity: usize, alloc: A) -> Self {
         unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } }
     }
 
@@ -885,6 +1086,49 @@ impl<T, A: Allocator> Vec<T, A> {
         (me.as_mut_ptr(), me.len(), me.capacity())
     }
 
+    #[doc(alias = "into_non_null_parts")]
+    /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity)`.
+    ///
+    /// Returns the `NonNull` pointer to the underlying data, the length of
+    /// the vector (in elements), and the allocated capacity of the
+    /// data (in elements). These are the same arguments in the same
+    /// order as the arguments to [`from_parts`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `Vec`. The only way to do
+    /// this is to convert the `NonNull` pointer, length, and capacity back
+    /// into a `Vec` with the [`from_parts`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_parts`]: Vec::from_parts
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_into_raw_parts, box_vec_non_null)]
+    ///
+    /// let v: Vec<i32> = vec![-1, 0, 1];
+    ///
+    /// let (ptr, len, cap) = v.into_parts();
+    ///
+    /// let rebuilt = unsafe {
+    ///     // We can now make changes to the components, such as
+    ///     // transmuting the raw pointer to a compatible type.
+    ///     let ptr = ptr.cast::<u32>();
+    ///
+    ///     Vec::from_parts(ptr, len, cap)
+    /// };
+    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// ```
+    #[must_use = "losing the pointer will leak memory"]
+    #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
+    // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_parts(self) -> (NonNull<T>, usize, usize) {
+        let (ptr, len, capacity) = self.into_raw_parts();
+        // SAFETY: A `Vec` always has a non-null pointer.
+        (unsafe { NonNull::new_unchecked(ptr) }, len, capacity)
+    }
+
     /// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity, allocator)`.
     ///
     /// Returns the raw pointer to the underlying data, the length of the vector (in elements),
@@ -934,6 +1178,54 @@ impl<T, A: Allocator> Vec<T, A> {
         (ptr, len, capacity, alloc)
     }
 
+    #[doc(alias = "into_non_null_parts_with_alloc")]
+    /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity, allocator)`.
+    ///
+    /// Returns the `NonNull` pointer to the underlying data, the length of the vector (in elements),
+    /// the allocated capacity of the data (in elements), and the allocator. These are the same
+    /// arguments in the same order as the arguments to [`from_parts_in`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `Vec`. The only way to do
+    /// this is to convert the `NonNull` pointer, length, and capacity back
+    /// into a `Vec` with the [`from_parts_in`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_parts_in`]: Vec::from_parts_in
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, vec_into_raw_parts, box_vec_non_null)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut v: Vec<i32, System> = Vec::new_in(System);
+    /// v.push(-1);
+    /// v.push(0);
+    /// v.push(1);
+    ///
+    /// let (ptr, len, cap, alloc) = v.into_parts_with_alloc();
+    ///
+    /// let rebuilt = unsafe {
+    ///     // We can now make changes to the components, such as
+    ///     // transmuting the raw pointer to a compatible type.
+    ///     let ptr = ptr.cast::<u32>();
+    ///
+    ///     Vec::from_parts_in(ptr, len, cap, alloc)
+    /// };
+    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// ```
+    #[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")]
+    // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_parts_with_alloc(self) -> (NonNull<T>, usize, usize, A) {
+        let (ptr, len, capacity, alloc) = self.into_raw_parts_with_alloc();
+        // SAFETY: A `Vec` always has a non-null pointer.
+        (unsafe { NonNull::new_unchecked(ptr) }, len, capacity, alloc)
+    }
+
     /// Returns the total number of elements the vector can hold without
     /// reallocating.
     ///
diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs
index 6646ae7bccb..e1f0b639bdf 100644
--- a/library/alloc/src/vec/spec_from_iter.rs
+++ b/library/alloc/src/vec/spec_from_iter.rs
@@ -51,7 +51,7 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
                 if has_advanced {
                     ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len());
                 }
-                return Vec::from_nonnull(it.buf, it.len(), it.cap);
+                return Vec::from_parts(it.buf, it.len(), it.cap);
             }
         }
 
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 4be2e5ef1ea..0154caa7c24 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -351,6 +351,9 @@ impl<T> MaybeUninit<T> {
     /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
     /// be null.
     ///
+    /// Note that if `T` has padding bytes, those bytes are *not* preserved when the
+    /// `MaybeUninit<T>` value is returned from this function, so those bytes will *not* be zeroed.
+    ///
     /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
     /// It is your responsibility to make sure `T` gets dropped if it got initialized.
     ///
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 035afbb8368..7dcca2707ba 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -99,7 +99,10 @@ impl<R: Read> BufReader<R> {
 impl<R: Read + ?Sized> BufReader<R> {
     /// Attempt to look ahead `n` bytes.
     ///
-    /// `n` must be less than `capacity`.
+    /// `n` must be less than or equal to `capacity`.
+    ///
+    /// the returned slice may be less than `n` bytes long if
+    /// end of file is reached.
     ///
     /// ## Examples
     ///
@@ -117,6 +120,7 @@ impl<R: Read + ?Sized> BufReader<R> {
     /// let mut s = String::new();
     /// rdr.read_to_string(&mut s).unwrap();
     /// assert_eq!(&s, "hello");
+    /// assert_eq!(rdr.peek(1).unwrap().len(), 0);
     /// ```
     #[unstable(feature = "bufreader_peek", issue = "128405")]
     pub fn peek(&mut self, n: usize) -> io::Result<&[u8]> {
@@ -125,7 +129,11 @@ impl<R: Read + ?Sized> BufReader<R> {
             if self.buf.pos() > 0 {
                 self.buf.backshift();
             }
-            self.buf.read_more(&mut self.inner)?;
+            let new = self.buf.read_more(&mut self.inner)?;
+            if new == 0 {
+                // end of file, no more bytes to read
+                return Ok(&self.buf.buffer()[..]);
+            }
             debug_assert_eq!(self.buf.pos(), 0);
         }
         Ok(&self.buf.buffer()[..n])
diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs
index ccd67fafb45..1bf84d8bef3 100644
--- a/library/std/src/io/buffered/bufreader/buffer.rs
+++ b/library/std/src/io/buffered/bufreader/buffer.rs
@@ -98,7 +98,7 @@ impl Buffer {
     }
 
     /// Read more bytes into the buffer without discarding any of its contents
-    pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<()> {
+    pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<usize> {
         let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]);
         let old_init = self.initialized - self.pos;
         unsafe {
@@ -107,7 +107,7 @@ impl Buffer {
         reader.read_buf(buf.unfilled())?;
         self.filled += buf.len();
         self.initialized += buf.init_len() - old_init;
-        Ok(())
+        Ok(buf.len())
     }
 
     /// Remove bytes that have already been read from the buffer.
diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml
index 087544397f5..5447565a4b0 100644
--- a/src/bootstrap/defaults/config.library.toml
+++ b/src/bootstrap/defaults/config.library.toml
@@ -13,4 +13,5 @@ lto = "off"
 
 [llvm]
 # Will download LLVM from CI if available on your platform.
-download-ci-llvm = "if-unchanged"
+# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead.
+download-ci-llvm = true
diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml
index 75ad37ce335..efb56996bcd 100644
--- a/src/bootstrap/defaults/config.tools.toml
+++ b/src/bootstrap/defaults/config.tools.toml
@@ -17,4 +17,5 @@ compiler-docs = true
 
 [llvm]
 # Will download LLVM from CI if available on your platform.
-download-ci-llvm = "if-unchanged"
+# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead.
+download-ci-llvm = true
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 99bcc6e0787..bedaa15ccb9 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -255,4 +255,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile",
     },
+    ChangeInfo {
+        change_id: 130202,
+        severity: ChangeSeverity::Info,
+        summary: "'tools' and 'library' profiles switched `download-ci-llvm` option from `if-unchanged` to `true`.",
+    },
 ];
diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md
index 3697ae38f9d..a5f99cc86f2 100644
--- a/src/doc/unstable-book/src/language-features/trait-upcasting.md
+++ b/src/doc/unstable-book/src/language-features/trait-upcasting.md
@@ -12,7 +12,6 @@ so long as `Bar: Foo`.
 
 ```rust,edition2018
 #![feature(trait_upcasting)]
-#![allow(incomplete_features)]
 
 trait Foo {}
 
diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr
index 8b01e8c3c10..1e28b9fbd86 100644
--- a/tests/ui/privacy/suggest-box-new.stderr
+++ b/tests/ui/privacy/suggest-box-new.stderr
@@ -44,7 +44,7 @@ LL |         wtf: Some(Box::new_zeroed()),
    |                      ~~~~~~~~~~~~~~
 LL |         wtf: Some(Box::new_in(_, _)),
    |                      ~~~~~~~~~~~~~~
-     and 10 other candidates
+     and 12 other candidates
 help: consider using the `Default` trait
    |
 LL |         wtf: Some(<Box as std::default::Default>::default()),
@@ -89,7 +89,7 @@ LL |     let _ = Box::new_zeroed();
    |                ~~~~~~~~~~~~~~
 LL |     let _ = Box::new_in(_, _);
    |                ~~~~~~~~~~~~~~
-     and 10 other candidates
+     and 12 other candidates
 help: consider using the `Default` trait
    |
 LL |     let _ = <Box as std::default::Default>::default();
diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr
index b27d9aef066..bfcc2307fd7 100644
--- a/tests/ui/suggestions/deref-path-method.stderr
+++ b/tests/ui/suggestions/deref-path-method.stderr
@@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll
       Vec::<T>::with_capacity
       Vec::<T>::try_with_capacity
       Vec::<T>::from_raw_parts
-      and 4 others
+      and 6 others
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: the function `contains` is implemented on `[_]`
    |
diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr
index 9cfeb7a5d09..e466f94d0d8 100644
--- a/tests/ui/ufcs/bad-builder.stderr
+++ b/tests/ui/ufcs/bad-builder.stderr
@@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<Q>` consider using one of the followi
       Vec::<T>::with_capacity
       Vec::<T>::try_with_capacity
       Vec::<T>::from_raw_parts
-      and 4 others
+      and 6 others
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: there is an associated function `new` with a similar name
    |