about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorStefan Lankes <stlankes@users.noreply.github.com>2020-04-04 07:41:05 +0200
committerGitHub <noreply@github.com>2020-04-04 07:41:05 +0200
commitaa223304dc130c5ace18d48c53b192b14088862e (patch)
tree1971ea5717f0e2ef2dc9468b3a0e96c209d481fe /src/libcore
parent9f6b96e461003853bf36052cfaf79b12e1c35413 (diff)
parent9e55101bb681010c82c3c827305e2665fc8f2aa0 (diff)
Merge branch 'master' into abi
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/alloc.rs1043
-rw-r--r--src/libcore/alloc/global.rs198
-rw-r--r--src/libcore/alloc/layout.rs346
-rw-r--r--src/libcore/alloc/mod.rs367
-rw-r--r--src/libcore/array/iter.rs18
-rw-r--r--src/libcore/clone.rs3
-rw-r--r--src/libcore/cmp.rs2
-rw-r--r--src/libcore/convert/mod.rs8
-rw-r--r--src/libcore/convert/num.rs15
-rw-r--r--src/libcore/fmt/mod.rs2
-rw-r--r--src/libcore/hint.rs2
-rw-r--r--src/libcore/intrinsics.rs20
-rw-r--r--src/libcore/iter/traits/iterator.rs8
-rw-r--r--src/libcore/macros/mod.rs16
-rw-r--r--src/libcore/marker.rs3
-rw-r--r--src/libcore/num/f32.rs14
-rw-r--r--src/libcore/num/f64.rs14
-rw-r--r--src/libcore/num/mod.rs6
-rw-r--r--src/libcore/ops/range.rs10
-rw-r--r--src/libcore/ptr/const_ptr.rs4
-rw-r--r--src/libcore/ptr/mut_ptr.rs4
-rw-r--r--src/libcore/raw.rs3
-rw-r--r--src/libcore/slice/mod.rs2
-rw-r--r--src/libcore/str/mod.rs41
-rw-r--r--src/libcore/str/pattern.rs85
-rw-r--r--src/libcore/time.rs4
26 files changed, 1097 insertions, 1141 deletions
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
deleted file mode 100644
index be20a1cde36..00000000000
--- a/src/libcore/alloc.rs
+++ /dev/null
@@ -1,1043 +0,0 @@
-//! Memory allocation APIs
-
-// ignore-tidy-undocumented-unsafe
-
-#![stable(feature = "alloc_module", since = "1.28.0")]
-
-use crate::cmp;
-use crate::fmt;
-use crate::mem;
-use crate::num::NonZeroUsize;
-use crate::ptr::{self, NonNull};
-use crate::usize;
-
-const fn size_align<T>() -> (usize, usize) {
-    (mem::size_of::<T>(), mem::align_of::<T>())
-}
-
-/// Layout of a block of memory.
-///
-/// An instance of `Layout` describes a particular layout of memory.
-/// You build a `Layout` up as an input to give to an allocator.
-///
-/// All layouts have an associated non-negative size and a
-/// power-of-two alignment.
-///
-/// (Note however that layouts are *not* required to have positive
-/// size, even though many allocators require that all memory
-/// requests have positive size. A caller to the `AllocRef::alloc`
-/// method must either ensure that conditions like this are met, or
-/// use specific allocators with looser requirements.)
-#[stable(feature = "alloc_layout", since = "1.28.0")]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[lang = "alloc_layout"]
-pub struct Layout {
-    // size of the requested block of memory, measured in bytes.
-    size_: usize,
-
-    // alignment of the requested block of memory, measured in bytes.
-    // we ensure that this is always a power-of-two, because API's
-    // like `posix_memalign` require it and it is a reasonable
-    // constraint to impose on Layout constructors.
-    //
-    // (However, we do not analogously require `align >= sizeof(void*)`,
-    //  even though that is *also* a requirement of `posix_memalign`.)
-    align_: NonZeroUsize,
-}
-
-impl Layout {
-    /// Constructs a `Layout` from a given `size` and `align`,
-    /// or returns `LayoutErr` if any of the following conditions
-    /// are not met:
-    ///
-    /// * `align` must not be zero,
-    ///
-    /// * `align` must be a power of two,
-    ///
-    /// * `size`, when rounded up to the nearest multiple of `align`,
-    ///    must not overflow (i.e., the rounded value must be less than
-    ///    `usize::MAX`).
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
-    #[inline]
-    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
-        if !align.is_power_of_two() {
-            return Err(LayoutErr { private: () });
-        }
-
-        // (power-of-two implies align != 0.)
-
-        // Rounded up size is:
-        //   size_rounded_up = (size + align - 1) & !(align - 1);
-        //
-        // We know from above that align != 0. If adding (align - 1)
-        // does not overflow, then rounding up will be fine.
-        //
-        // Conversely, &-masking with !(align - 1) will subtract off
-        // only low-order-bits. Thus if overflow occurs with the sum,
-        // the &-mask cannot subtract enough to undo that overflow.
-        //
-        // Above implies that checking for summation overflow is both
-        // necessary and sufficient.
-        if size > usize::MAX - (align - 1) {
-            return Err(LayoutErr { private: () });
-        }
-
-        unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
-    }
-
-    /// Creates a layout, bypassing all checks.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe as it does not verify the preconditions from
-    /// [`Layout::from_size_align`](#method.from_size_align).
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
-    #[inline]
-    pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
-        Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
-    }
-
-    /// The minimum size in bytes for a memory block of this layout.
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
-    #[inline]
-    pub const fn size(&self) -> usize {
-        self.size_
-    }
-
-    /// The minimum byte alignment for a memory block of this layout.
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
-    #[inline]
-    pub const fn align(&self) -> usize {
-        self.align_.get()
-    }
-
-    /// Constructs a `Layout` suitable for holding a value of type `T`.
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
-    #[inline]
-    pub const fn new<T>() -> Self {
-        let (size, align) = size_align::<T>();
-        // Note that the align is guaranteed by rustc to be a power of two and
-        // the size+align combo is guaranteed to fit in our address space. As a
-        // result use the unchecked constructor here to avoid inserting code
-        // that panics if it isn't optimized well enough.
-        unsafe { Layout::from_size_align_unchecked(size, align) }
-    }
-
-    /// Produces layout describing a record that could be used to
-    /// allocate backing structure for `T` (which could be a trait
-    /// or other unsized type like a slice).
-    #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[inline]
-    pub fn for_value<T: ?Sized>(t: &T) -> Self {
-        let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
-        // See rationale in `new` for why this is using an unsafe variant below
-        debug_assert!(Layout::from_size_align(size, align).is_ok());
-        unsafe { Layout::from_size_align_unchecked(size, align) }
-    }
-
-    /// Produces layout describing a record that could be used to
-    /// allocate backing structure for `T` (which could be a trait
-    /// or other unsized type like a slice).
-    ///
-    /// # Safety
-    ///
-    /// This function is only safe to call if the following conditions hold:
-    ///
-    /// - If `T` is `Sized`, this function is always safe to call.
-    /// - If the unsized tail of `T` is:
-    ///     - a [slice], then the length of the slice tail must be an intialized
-    ///       integer, and the size of the *entire value*
-    ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
-    ///     - a [trait object], then the vtable part of the pointer must point
-    ///       to a valid vtable acquired by an unsizing coersion, and the size
-    ///       of the *entire value* (dynamic tail length + statically sized prefix)
-    ///       must fit in `isize`.
-    ///     - an (unstable) [extern type], then this function is always safe to
-    ///       call, but may panic or otherwise return the wrong value, as the
-    ///       extern type's layout is not known. This is the same behavior as
-    ///       [`Layout::for_value`] on a reference to an extern type tail.
-    ///     - otherwise, it is conservatively not allowed to call this function.
-    ///
-    /// [slice]: ../../std/primitive.slice.html
-    /// [trait object]: ../../book/ch17-02-trait-objects.html
-    /// [extern type]: ../../unstable-book/language-features/extern-types.html
-    #[inline]
-    #[cfg(not(bootstrap))]
-    #[unstable(feature = "layout_for_ptr", issue = "69835")]
-    pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
-        let (size, align) = (mem::size_of_val_raw(t), mem::align_of_val_raw(t));
-        // See rationale in `new` for why this is using an unsafe variant below
-        debug_assert!(Layout::from_size_align(size, align).is_ok());
-        Layout::from_size_align_unchecked(size, align)
-    }
-
-    /// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
-    ///
-    /// Note that the pointer value may potentially represent a valid pointer,
-    /// which means this must not be used as a "not yet initialized"
-    /// sentinel value. Types that lazily allocate must track initialization by
-    /// some other means.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    pub const fn dangling(&self) -> NonNull<u8> {
-        // align is non-zero and a power of two
-        unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
-    }
-
-    /// Creates a layout describing the record that can hold a value
-    /// of the same layout as `self`, but that also is aligned to
-    /// alignment `align` (measured in bytes).
-    ///
-    /// If `self` already meets the prescribed alignment, then returns
-    /// `self`.
-    ///
-    /// Note that this method does not add any padding to the overall
-    /// size, regardless of whether the returned layout has a different
-    /// alignment. In other words, if `K` has size 16, `K.align_to(32)`
-    /// will *still* have size 16.
-    ///
-    /// Returns an error if the combination of `self.size()` and the given
-    /// `align` violates the conditions listed in
-    /// [`Layout::from_size_align`](#method.from_size_align).
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
-        Layout::from_size_align(self.size(), cmp::max(self.align(), align))
-    }
-
-    /// Returns the amount of padding we must insert after `self`
-    /// to ensure that the following address will satisfy `align`
-    /// (measured in bytes).
-    ///
-    /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
-    /// returns 3, because that is the minimum number of bytes of
-    /// padding required to get a 4-aligned address (assuming that the
-    /// corresponding memory block starts at a 4-aligned address).
-    ///
-    /// The return value of this function has no meaning if `align` is
-    /// not a power-of-two.
-    ///
-    /// Note that the utility of the returned value requires `align`
-    /// to be less than or equal to the alignment of the starting
-    /// address for the whole allocated block of memory. One way to
-    /// satisfy this constraint is to ensure `align <= self.align()`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
-    #[inline]
-    pub const fn padding_needed_for(&self, align: usize) -> usize {
-        let len = self.size();
-
-        // Rounded up value is:
-        //   len_rounded_up = (len + align - 1) & !(align - 1);
-        // and then we return the padding difference: `len_rounded_up - len`.
-        //
-        // We use modular arithmetic throughout:
-        //
-        // 1. align is guaranteed to be > 0, so align - 1 is always
-        //    valid.
-        //
-        // 2. `len + align - 1` can overflow by at most `align - 1`,
-        //    so the &-mask with `!(align - 1)` will ensure that in the
-        //    case of overflow, `len_rounded_up` will itself be 0.
-        //    Thus the returned padding, when added to `len`, yields 0,
-        //    which trivially satisfies the alignment `align`.
-        //
-        // (Of course, attempts to allocate blocks of memory whose
-        // size and padding overflow in the above manner should cause
-        // the allocator to yield an error anyway.)
-
-        let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
-        len_rounded_up.wrapping_sub(len)
-    }
-
-    /// Creates a layout by rounding the size of this layout up to a multiple
-    /// of the layout's alignment.
-    ///
-    /// This is equivalent to adding the result of `padding_needed_for`
-    /// to the layout's current size.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn pad_to_align(&self) -> Layout {
-        let pad = self.padding_needed_for(self.align());
-        // This cannot overflow. Quoting from the invariant of Layout:
-        // > `size`, when rounded up to the nearest multiple of `align`,
-        // > must not overflow (i.e., the rounded value must be less than
-        // > `usize::MAX`)
-        let new_size = self.size() + pad;
-
-        Layout::from_size_align(new_size, self.align()).unwrap()
-    }
-
-    /// Creates a layout describing the record for `n` instances of
-    /// `self`, with a suitable amount of padding between each to
-    /// ensure that each instance is given its requested size and
-    /// alignment. On success, returns `(k, offs)` where `k` is the
-    /// layout of the array and `offs` is the distance between the start
-    /// of each element in the array.
-    ///
-    /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
-        // This cannot overflow. Quoting from the invariant of Layout:
-        // > `size`, when rounded up to the nearest multiple of `align`,
-        // > must not overflow (i.e., the rounded value must be less than
-        // > `usize::MAX`)
-        let padded_size = self.size() + self.padding_needed_for(self.align());
-        let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
-
-        unsafe {
-            // self.align is already known to be valid and alloc_size has been
-            // padded already.
-            Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size))
-        }
-    }
-
-    /// Creates a layout describing the record for `self` followed by
-    /// `next`, including any necessary padding to ensure that `next`
-    /// will be properly aligned. Note that the resulting layout will
-    /// satisfy the alignment properties of both `self` and `next`.
-    ///
-    /// The resulting layout will be the same as that of a C struct containing
-    /// two fields with the layouts of `self` and `next`, in that order.
-    ///
-    /// Returns `Some((k, offset))`, where `k` is layout of the concatenated
-    /// record and `offset` is the relative location, in bytes, of the
-    /// start of the `next` embedded within the concatenated record
-    /// (assuming that the record itself starts at offset 0).
-    ///
-    /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
-        let new_align = cmp::max(self.align(), next.align());
-        let pad = self.padding_needed_for(next.align());
-
-        let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
-        let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
-
-        let layout = Layout::from_size_align(new_size, new_align)?;
-        Ok((layout, offset))
-    }
-
-    /// Creates a layout describing the record for `n` instances of
-    /// `self`, with no padding between each instance.
-    ///
-    /// Note that, unlike `repeat`, `repeat_packed` does not guarantee
-    /// that the repeated instances of `self` will be properly
-    /// aligned, even if a given instance of `self` is properly
-    /// aligned. In other words, if the layout returned by
-    /// `repeat_packed` is used to allocate an array, it is not
-    /// guaranteed that all elements in the array will be properly
-    /// aligned.
-    ///
-    /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
-        let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
-        Layout::from_size_align(size, self.align())
-    }
-
-    /// Creates a layout describing the record for `self` followed by
-    /// `next` with no additional padding between the two. Since no
-    /// padding is inserted, the alignment of `next` is irrelevant,
-    /// and is not incorporated *at all* into the resulting layout.
-    ///
-    /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
-        let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
-        Layout::from_size_align(new_size, self.align())
-    }
-
-    /// Creates a layout describing the record for a `[T; n]`.
-    ///
-    /// On arithmetic overflow, returns `LayoutErr`.
-    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
-    #[inline]
-    pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
-        Layout::new::<T>().repeat(n).map(|(k, offs)| {
-            debug_assert!(offs == mem::size_of::<T>());
-            k
-        })
-    }
-}
-
-/// The parameters given to `Layout::from_size_align`
-/// or some other `Layout` constructor
-/// do not satisfy its documented constraints.
-#[stable(feature = "alloc_layout", since = "1.28.0")]
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct LayoutErr {
-    private: (),
-}
-
-// (we need this for downstream impl of trait Error)
-#[stable(feature = "alloc_layout", since = "1.28.0")]
-impl fmt::Display for LayoutErr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str("invalid parameters to Layout::from_size_align")
-    }
-}
-
-/// The `AllocErr` error indicates an allocation failure
-/// that may be due to resource exhaustion or to
-/// something wrong when combining the given input arguments with this
-/// allocator.
-#[unstable(feature = "allocator_api", issue = "32838")]
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct AllocErr;
-
-// (we need this for downstream impl of trait Error)
-#[unstable(feature = "allocator_api", issue = "32838")]
-impl fmt::Display for AllocErr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str("memory allocation failed")
-    }
-}
-
-/// The `CannotReallocInPlace` error is used when [`grow_in_place`] or
-/// [`shrink_in_place`] were unable to reuse the given memory block for
-/// a requested layout.
-///
-/// [`grow_in_place`]: ./trait.AllocRef.html#method.grow_in_place
-/// [`shrink_in_place`]: ./trait.AllocRef.html#method.shrink_in_place
-#[unstable(feature = "allocator_api", issue = "32838")]
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct CannotReallocInPlace;
-
-#[unstable(feature = "allocator_api", issue = "32838")]
-impl CannotReallocInPlace {
-    pub fn description(&self) -> &str {
-        "cannot reallocate allocator's memory in place"
-    }
-}
-
-// (we need this for downstream impl of trait Error)
-#[unstable(feature = "allocator_api", issue = "32838")]
-impl fmt::Display for CannotReallocInPlace {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.description())
-    }
-}
-
-/// A memory allocator that can be registered as the standard library’s default
-/// through the `#[global_allocator]` attribute.
-///
-/// Some of the methods require that a memory block be *currently
-/// allocated* via an allocator. This means that:
-///
-/// * the starting address for that memory block was previously
-///   returned by a previous call to an allocation method
-///   such as `alloc`, and
-///
-/// * the memory block has not been subsequently deallocated, where
-///   blocks are deallocated either by being passed to a deallocation
-///   method such as `dealloc` or by being
-///   passed to a reallocation method that returns a non-null pointer.
-///
-///
-/// # Example
-///
-/// ```no_run
-/// use std::alloc::{GlobalAlloc, Layout, alloc};
-/// use std::ptr::null_mut;
-///
-/// struct MyAllocator;
-///
-/// unsafe impl GlobalAlloc for MyAllocator {
-///     unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
-///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
-/// }
-///
-/// #[global_allocator]
-/// static A: MyAllocator = MyAllocator;
-///
-/// fn main() {
-///     unsafe {
-///         assert!(alloc(Layout::new::<u32>()).is_null())
-///     }
-/// }
-/// ```
-///
-/// # Safety
-///
-/// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
-/// implementors must ensure that they adhere to these contracts:
-///
-/// * It's undefined behavior if global allocators unwind. This restriction may
-///   be lifted in the future, but currently a panic from any of these
-///   functions may lead to memory unsafety.
-///
-/// * `Layout` queries and calculations in general must be correct. Callers of
-///   this trait are allowed to rely on the contracts defined on each method,
-///   and implementors must ensure such contracts remain true.
-#[stable(feature = "global_alloc", since = "1.28.0")]
-pub unsafe trait GlobalAlloc {
-    /// Allocate memory as described by the given `layout`.
-    ///
-    /// Returns a pointer to newly-allocated memory,
-    /// or null to indicate allocation failure.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure that `layout` has non-zero size.
-    ///
-    /// (Extension subtraits might provide more specific bounds on
-    /// behavior, e.g., guarantee a sentinel address or a null pointer
-    /// in response to a zero-size allocation request.)
-    ///
-    /// The allocated block of memory may or may not be initialized.
-    ///
-    /// # Errors
-    ///
-    /// Returning a null pointer indicates that either memory is exhausted
-    /// or `layout` does not meet this allocator's size or alignment constraints.
-    ///
-    /// Implementations are encouraged to return null on memory
-    /// exhaustion rather than aborting, but this is not
-    /// a strict requirement. (Specifically: it is *legal* to
-    /// implement this trait atop an underlying native allocation
-    /// library that aborts on memory exhaustion.)
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    #[stable(feature = "global_alloc", since = "1.28.0")]
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8;
-
-    /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must denote a block of memory currently allocated via
-    ///   this allocator,
-    ///
-    /// * `layout` must be the same layout that was used
-    ///   to allocate that block of memory,
-    #[stable(feature = "global_alloc", since = "1.28.0")]
-    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
-
-    /// Behaves like `alloc`, but also ensures that the contents
-    /// are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `alloc` is.
-    /// However the allocated block of memory is guaranteed to be initialized.
-    ///
-    /// # Errors
-    ///
-    /// Returning a null pointer indicates that either memory is exhausted
-    /// or `layout` does not meet allocator's size or alignment constraints,
-    /// just as in `alloc`.
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    #[stable(feature = "global_alloc", since = "1.28.0")]
-    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-        let size = layout.size();
-        let ptr = self.alloc(layout);
-        if !ptr.is_null() {
-            ptr::write_bytes(ptr, 0, size);
-        }
-        ptr
-    }
-
-    /// Shrink or grow a block of memory to the given `new_size`.
-    /// The block is described by the given `ptr` pointer and `layout`.
-    ///
-    /// If this returns a non-null pointer, then ownership of the memory block
-    /// referenced by `ptr` has been transferred to this allocator.
-    /// The memory may or may not have been deallocated,
-    /// and should be considered unusable (unless of course it was
-    /// transferred back to the caller again via the return value of
-    /// this method). The new memory block is allocated with `layout`, but
-    /// with the `size` updated to `new_size`.
-    ///
-    /// If this method returns null, then ownership of the memory
-    /// block has not been transferred to this allocator, and the
-    /// contents of the memory block are unaltered.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must be currently allocated via this allocator,
-    ///
-    /// * `layout` must be the same layout that was used
-    ///   to allocate that block of memory,
-    ///
-    /// * `new_size` must be greater than zero.
-    ///
-    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
-    ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
-    ///
-    /// (Extension subtraits might provide more specific bounds on
-    /// behavior, e.g., guarantee a sentinel address or a null pointer
-    /// in response to a zero-size allocation request.)
-    ///
-    /// # Errors
-    ///
-    /// Returns null if the new layout does not meet the size
-    /// and alignment constraints of the allocator, or if reallocation
-    /// otherwise fails.
-    ///
-    /// Implementations are encouraged to return null on memory
-    /// exhaustion rather than panicking or aborting, but this is not
-    /// a strict requirement. (Specifically: it is *legal* to
-    /// implement this trait atop an underlying native allocation
-    /// library that aborts on memory exhaustion.)
-    ///
-    /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    #[stable(feature = "global_alloc", since = "1.28.0")]
-    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-        let new_ptr = self.alloc(new_layout);
-        if !new_ptr.is_null() {
-            ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
-            self.dealloc(ptr, layout);
-        }
-        new_ptr
-    }
-}
-
-/// An implementation of `AllocRef` can allocate, reallocate, and
-/// deallocate arbitrary blocks of data described via `Layout`.
-///
-/// `AllocRef` is designed to be implemented on ZSTs, references, or
-/// smart pointers because having an allocator like `MyAlloc([u8; N])`
-/// cannot be moved, without updating the pointers to the allocated
-/// memory.
-///
-/// Some of the methods require that a memory block be *currently
-/// allocated* via an allocator. This means that:
-///
-/// * the starting address for that memory block was previously
-///   returned by a previous call to an allocation method (`alloc`,
-///   `alloc_zeroed`) or reallocation method (`realloc`), and
-///
-/// * the memory block has not been subsequently deallocated, where
-///   blocks are deallocated either by being passed to a deallocation
-///   method (`dealloc`) or by being passed to a reallocation method
-///  (see above) that returns `Ok`.
-///
-/// Unlike [`GlobalAlloc`], zero-sized allocations are allowed in
-/// `AllocRef`. If an underlying allocator does not support this (like
-/// jemalloc) or return a null pointer (such as `libc::malloc`), this case
-/// must be caught. In this case [`Layout::dangling()`] can be used to
-/// create a dangling, but aligned `NonNull<u8>`.
-///
-/// Some of the methods require that a layout *fit* a memory block.
-/// What it means for a layout to "fit" a memory block means (or
-/// equivalently, for a memory block to "fit" a layout) is that the
-/// following two conditions must hold:
-///
-/// 1. The block's starting address must be aligned to `layout.align()`.
-///
-/// 2. The block's size must fall in the range `[use_min, use_max]`, where:
-///
-///    * `use_min` is `layout.size()`, and
-///
-///    * `use_max` is the capacity that was returned.
-///
-/// Note that:
-///
-///  * the size of the layout most recently used to allocate the block
-///    is guaranteed to be in the range `[use_min, use_max]`, and
-///
-///  * a lower-bound on `use_max` can be safely approximated by a call to
-///    `usable_size`.
-///
-///  * if a layout `k` fits a memory block (denoted by `ptr`)
-///    currently allocated via an allocator `a`, then it is legal to
-///    use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`.
-///
-///  * if an allocator does not support overallocating, it is fine to
-///    simply return `layout.size()` as the allocated size.
-///
-/// [`GlobalAlloc`]: self::GlobalAlloc
-/// [`Layout::dangling()`]: self::Layout::dangling
-///
-/// # Safety
-///
-/// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
-/// implementors must ensure that they adhere to these contracts:
-///
-/// * Pointers returned from allocation functions must point to valid memory and
-///   retain their validity until at least one instance of `AllocRef` is dropped
-///   itself.
-///
-/// * Cloning or moving the allocator must not invalidate pointers returned
-///   from this allocator. Cloning must return a reference to the same allocator.
-///
-/// * `Layout` queries and calculations in general must be correct. Callers of
-///   this trait are allowed to rely on the contracts defined on each method,
-///   and implementors must ensure such contracts remain true.
-///
-/// Note that this list may get tweaked over time as clarifications are made in
-/// the future.
-#[unstable(feature = "allocator_api", issue = "32838")]
-pub unsafe trait AllocRef {
-    /// On success, returns a pointer meeting the size and alignment
-    /// guarantees of `layout` and the actual size of the allocated block,
-    /// which must be greater than or equal to `layout.size()`.
-    ///
-    /// If this method returns an `Ok(addr)`, then the `addr` returned
-    /// will be non-null address pointing to a block of storage
-    /// suitable for holding an instance of `layout`.
-    ///
-    /// The returned block of storage may or may not have its contents
-    /// initialized. (Extension subtraits might restrict this
-    /// behavior, e.g., to ensure initialization to particular sets of
-    /// bit patterns.)
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints.
-    ///
-    /// Implementations are encouraged to return `Err` on memory
-    /// exhaustion rather than panicking or aborting, but this is not
-    /// a strict requirement. (Specifically: it is *legal* to
-    /// implement this trait atop an underlying native allocation
-    /// library that aborts on memory exhaustion.)
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
-
-    /// Deallocate the memory referenced by `ptr`.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must denote a block of memory currently allocated via
-    ///   this allocator,
-    ///
-    /// * `layout` must *fit* that block of memory,
-    ///
-    /// * In addition to fitting the block of memory `layout`, the
-    ///   alignment of the `layout` must match the alignment used
-    ///   to allocate that block of memory.
-    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
-
-    /// Behaves like `alloc`, but also ensures that the contents
-    /// are set to zero before being returned.
-    ///
-    /// # Errors
-    ///
-    /// Returning `Err` indicates that either memory is exhausted or
-    /// `layout` does not meet allocator's size or alignment
-    /// constraints, just as in `alloc`.
-    ///
-    /// Clients wishing to abort computation in response to an
-    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
-        let size = layout.size();
-        let result = self.alloc(layout);
-        if let Ok((p, _)) = result {
-            unsafe { ptr::write_bytes(p.as_ptr(), 0, size) }
-        }
-        result
-    }
-
-    // == METHODS FOR MEMORY REUSE ==
-    // realloc, realloc_zeroed, grow_in_place, grow_in_place_zeroed, shrink_in_place
-
-    /// Returns a pointer suitable for holding data described by
-    /// a new layout with `layout`’s alignment and a size given
-    /// by `new_size` and the actual size of the allocated block.
-    /// The latter is greater than or equal to `layout.size()`.
-    /// To accomplish this, the allocator may extend or shrink
-    /// the allocation referenced by `ptr` to fit the new layout.
-    ///
-    /// If this returns `Ok`, then ownership of the memory block
-    /// referenced by `ptr` has been transferred to this
-    /// allocator. The memory may or may not have been freed, and
-    /// should be considered unusable (unless of course it was
-    /// transferred back to the caller again via the return value of
-    /// this method).
-    ///
-    /// If this method returns `Err`, then ownership of the memory
-    /// block has not been transferred to this allocator, and the
-    /// contents of the memory block are unaltered.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must be currently allocated via this allocator,
-    ///
-    /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
-    ///   argument need not fit it.)
-    ///
-    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
-    ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
-    ///
-    /// (Extension subtraits might provide more specific bounds on
-    /// behavior, e.g., guarantee a sentinel address or a null pointer
-    /// in response to a zero-size allocation request.)
-    ///
-    /// # Errors
-    ///
-    /// Returns `Err` only if the new layout
-    /// does not meet the allocator's size
-    /// and alignment constraints of the allocator, or if reallocation
-    /// otherwise fails.
-    ///
-    /// Implementations are encouraged to return `Err` on memory
-    /// exhaustion rather than panicking or aborting, but this is not
-    /// a strict requirement. (Specifically: it is *legal* to
-    /// implement this trait atop an underlying native allocation
-    /// library that aborts on memory exhaustion.)
-    ///
-    /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn realloc(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<(NonNull<u8>, usize), AllocErr> {
-        let old_size = layout.size();
-
-        if new_size > old_size {
-            if let Ok(size) = self.grow_in_place(ptr, layout, new_size) {
-                return Ok((ptr, size));
-            }
-        } else if new_size < old_size {
-            if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
-                return Ok((ptr, size));
-            }
-        } else {
-            return Ok((ptr, new_size));
-        }
-
-        // otherwise, fall back on alloc + copy + dealloc.
-        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-        let result = self.alloc(new_layout);
-        if let Ok((new_ptr, _)) = result {
-            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
-            self.dealloc(ptr, layout);
-        }
-        result
-    }
-
-    /// Behaves like `realloc`, but also ensures that the new contents
-    /// are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `realloc` is.
-    ///
-    /// # Errors
-    ///
-    /// Returns `Err` only if the new layout
-    /// does not meet the allocator's size
-    /// and alignment constraints of the allocator, or if reallocation
-    /// otherwise fails.
-    ///
-    /// Implementations are encouraged to return `Err` on memory
-    /// exhaustion rather than panicking or aborting, but this is not
-    /// a strict requirement. (Specifically: it is *legal* to
-    /// implement this trait atop an underlying native allocation
-    /// library that aborts on memory exhaustion.)
-    ///
-    /// Clients wishing to abort computation in response to a
-    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
-    /// rather than directly invoking `panic!` or similar.
-    ///
-    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
-    unsafe fn realloc_zeroed(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<(NonNull<u8>, usize), AllocErr> {
-        let old_size = layout.size();
-
-        if new_size > old_size {
-            if let Ok(size) = self.grow_in_place_zeroed(ptr, layout, new_size) {
-                return Ok((ptr, size));
-            }
-        } else if new_size < old_size {
-            if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) {
-                return Ok((ptr, size));
-            }
-        } else {
-            return Ok((ptr, new_size));
-        }
-
-        // otherwise, fall back on alloc + copy + dealloc.
-        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
-        let result = self.alloc_zeroed(new_layout);
-        if let Ok((new_ptr, _)) = result {
-            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size));
-            self.dealloc(ptr, layout);
-        }
-        result
-    }
-
-    /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
-    ///
-    /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_size`, and thus can
-    /// be used to carry data of a layout of that size and same alignment as
-    /// `layout`. The returned value is the new size of the allocated block.
-    /// (The allocator is allowed to expend effort to accomplish this, such
-    /// as extending the memory block to include successor blocks, or virtual
-    /// memory tricks.)
-    ///
-    /// Regardless of what this method returns, ownership of the
-    /// memory block referenced by `ptr` has not been transferred, and
-    /// the contents of the memory block are unaltered.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must be currently allocated via this allocator,
-    ///
-    /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_size` argument need not fit it,
-    ///
-    /// * `new_size` must not be less than `layout.size()`,
-    ///
-    /// # Errors
-    ///
-    /// Returns `Err(CannotReallocInPlace)` when the allocator is
-    /// unable to assert that the memory block referenced by `ptr`
-    /// could fit `layout`.
-    ///
-    /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
-    /// function; clients are expected either to be able to recover from
-    /// `grow_in_place` failures without aborting, or to fall back on
-    /// another reallocation method before resorting to an abort.
-    #[inline]
-    unsafe fn grow_in_place(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<usize, CannotReallocInPlace> {
-        let _ = ptr;
-        let _ = layout;
-        let _ = new_size;
-        Err(CannotReallocInPlace)
-    }
-
-    /// Behaves like `grow_in_place`, but also ensures that the new
-    /// contents are set to zero before being returned.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe for the same reasons that `grow_in_place` is.
-    ///
-    /// # Errors
-    ///
-    /// Returns `Err(CannotReallocInPlace)` when the allocator is
-    /// unable to assert that the memory block referenced by `ptr`
-    /// could fit `layout`.
-    ///
-    /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
-    /// function; clients are expected either to be able to recover from
-    /// `grow_in_place` failures without aborting, or to fall back on
-    /// another reallocation method before resorting to an abort.
-    unsafe fn grow_in_place_zeroed(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<usize, CannotReallocInPlace> {
-        let size = self.grow_in_place(ptr, layout, new_size)?;
-        ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size());
-        Ok(size)
-    }
-
-    /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
-    ///
-    /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_size`, and
-    /// thus can only be used to carry data of that smaller
-    /// layout. The returned value is the new size the allocated block.
-    /// (The allocator is allowed to take advantage of this,
-    /// carving off portions of the block for reuse elsewhere.) The
-    /// truncated contents of the block within the smaller layout are
-    /// unaltered, and ownership of block has not been transferred.
-    ///
-    /// If this returns `Err`, then the memory block is considered to
-    /// still represent the original (larger) `layout`. None of the
-    /// block has been carved off for reuse elsewhere, ownership of
-    /// the memory block has not been transferred, and the contents of
-    /// the memory block are unaltered.
-    ///
-    /// # Safety
-    ///
-    /// This function is unsafe because undefined behavior can result
-    /// if the caller does not ensure all of the following:
-    ///
-    /// * `ptr` must be currently allocated via this allocator,
-    ///
-    /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_size` argument need not fit it,
-    ///
-    /// * `new_size` must not be greater than `layout.size()`,
-    ///
-    /// # Errors
-    ///
-    /// Returns `Err(CannotReallocInPlace)` when the allocator is
-    /// unable to assert that the memory block referenced by `ptr`
-    /// could fit `layout`.
-    ///
-    /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
-    /// function; clients are expected either to be able to recover from
-    /// `shrink_in_place` failures without aborting, or to fall back
-    /// on another reallocation method before resorting to an abort.
-    #[inline]
-    unsafe fn shrink_in_place(
-        &mut self,
-        ptr: NonNull<u8>,
-        layout: Layout,
-        new_size: usize,
-    ) -> Result<usize, CannotReallocInPlace> {
-        let _ = ptr;
-        let _ = layout;
-        let _ = new_size;
-        Err(CannotReallocInPlace)
-    }
-}
diff --git a/src/libcore/alloc/global.rs b/src/libcore/alloc/global.rs
new file mode 100644
index 00000000000..147fe696ac0
--- /dev/null
+++ b/src/libcore/alloc/global.rs
@@ -0,0 +1,198 @@
+use crate::alloc::Layout;
+use crate::cmp;
+use crate::ptr;
+
+/// A memory allocator that can be registered as the standard library’s default
+/// through the `#[global_allocator]` attribute.
+///
+/// Some of the methods require that a memory block be *currently
+/// allocated* via an allocator. This means that:
+///
+/// * the starting address for that memory block was previously
+///   returned by a previous call to an allocation method
+///   such as `alloc`, and
+///
+/// * the memory block has not been subsequently deallocated, where
+///   blocks are deallocated either by being passed to a deallocation
+///   method such as `dealloc` or by being
+///   passed to a reallocation method that returns a non-null pointer.
+///
+///
+/// # Example
+///
+/// ```no_run
+/// use std::alloc::{GlobalAlloc, Layout, alloc};
+/// use std::ptr::null_mut;
+///
+/// struct MyAllocator;
+///
+/// unsafe impl GlobalAlloc for MyAllocator {
+///     unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
+///     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
+/// }
+///
+/// #[global_allocator]
+/// static A: MyAllocator = MyAllocator;
+///
+/// fn main() {
+///     unsafe {
+///         assert!(alloc(Layout::new::<u32>()).is_null())
+///     }
+/// }
+/// ```
+///
+/// # Safety
+///
+/// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
+/// implementors must ensure that they adhere to these contracts:
+///
+/// * It's undefined behavior if global allocators unwind. This restriction may
+///   be lifted in the future, but currently a panic from any of these
+///   functions may lead to memory unsafety.
+///
+/// * `Layout` queries and calculations in general must be correct. Callers of
+///   this trait are allowed to rely on the contracts defined on each method,
+///   and implementors must ensure such contracts remain true.
+#[stable(feature = "global_alloc", since = "1.28.0")]
+pub unsafe trait GlobalAlloc {
+    /// Allocate memory as described by the given `layout`.
+    ///
+    /// Returns a pointer to newly-allocated memory,
+    /// or null to indicate allocation failure.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because undefined behavior can result
+    /// if the caller does not ensure that `layout` has non-zero size.
+    ///
+    /// (Extension subtraits might provide more specific bounds on
+    /// behavior, e.g., guarantee a sentinel address or a null pointer
+    /// in response to a zero-size allocation request.)
+    ///
+    /// The allocated block of memory may or may not be initialized.
+    ///
+    /// # Errors
+    ///
+    /// Returning a null pointer indicates that either memory is exhausted
+    /// or `layout` does not meet this allocator's size or alignment constraints.
+    ///
+    /// Implementations are encouraged to return null on memory
+    /// exhaustion rather than aborting, but this is not
+    /// a strict requirement. (Specifically: it is *legal* to
+    /// implement this trait atop an underlying native allocation
+    /// library that aborts on memory exhaustion.)
+    ///
+    /// Clients wishing to abort computation in response to an
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
+    /// rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    #[stable(feature = "global_alloc", since = "1.28.0")]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8;
+
+    /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because undefined behavior can result
+    /// if the caller does not ensure all of the following:
+    ///
+    /// * `ptr` must denote a block of memory currently allocated via
+    ///   this allocator,
+    ///
+    /// * `layout` must be the same layout that was used
+    ///   to allocate that block of memory,
+    #[stable(feature = "global_alloc", since = "1.28.0")]
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
+
+    /// Behaves like `alloc`, but also ensures that the contents
+    /// are set to zero before being returned.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe for the same reasons that `alloc` is.
+    /// However the allocated block of memory is guaranteed to be initialized.
+    ///
+    /// # Errors
+    ///
+    /// Returning a null pointer indicates that either memory is exhausted
+    /// or `layout` does not meet allocator's size or alignment constraints,
+    /// just as in `alloc`.
+    ///
+    /// Clients wishing to abort computation in response to an
+    /// allocation error are encouraged to call the [`handle_alloc_error`] function,
+    /// rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    #[stable(feature = "global_alloc", since = "1.28.0")]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        let size = layout.size();
+        let ptr = self.alloc(layout);
+        if !ptr.is_null() {
+            ptr::write_bytes(ptr, 0, size);
+        }
+        ptr
+    }
+
+    /// Shrink or grow a block of memory to the given `new_size`.
+    /// The block is described by the given `ptr` pointer and `layout`.
+    ///
+    /// If this returns a non-null pointer, then ownership of the memory block
+    /// referenced by `ptr` has been transferred to this allocator.
+    /// The memory may or may not have been deallocated,
+    /// and should be considered unusable (unless of course it was
+    /// transferred back to the caller again via the return value of
+    /// this method). The new memory block is allocated with `layout`, but
+    /// with the `size` updated to `new_size`.
+    ///
+    /// If this method returns null, then ownership of the memory
+    /// block has not been transferred to this allocator, and the
+    /// contents of the memory block are unaltered.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because undefined behavior can result
+    /// if the caller does not ensure all of the following:
+    ///
+    /// * `ptr` must be currently allocated via this allocator,
+    ///
+    /// * `layout` must be the same layout that was used
+    ///   to allocate that block of memory,
+    ///
+    /// * `new_size` must be greater than zero.
+    ///
+    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
+    ///   must not overflow (i.e., the rounded value must be less than `usize::MAX`).
+    ///
+    /// (Extension subtraits might provide more specific bounds on
+    /// behavior, e.g., guarantee a sentinel address or a null pointer
+    /// in response to a zero-size allocation request.)
+    ///
+    /// # Errors
+    ///
+    /// Returns null if the new layout does not meet the size
+    /// and alignment constraints of the allocator, or if reallocation
+    /// otherwise fails.
+    ///
+    /// Implementations are encouraged to return null on memory
+    /// exhaustion rather than panicking or aborting, but this is not
+    /// a strict requirement. (Specifically: it is *legal* to
+    /// implement this trait atop an underlying native allocation
+    /// library that aborts on memory exhaustion.)
+    ///
+    /// Clients wishing to abort computation in response to a
+    /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
+    /// rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    #[stable(feature = "global_alloc", since = "1.28.0")]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+        let new_ptr = self.alloc(new_layout);
+        if !new_ptr.is_null() {
+            ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
+            self.dealloc(ptr, layout);
+        }
+        new_ptr
+    }
+}
diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs
new file mode 100644
index 00000000000..fa644cfe99e
--- /dev/null
+++ b/src/libcore/alloc/layout.rs
@@ -0,0 +1,346 @@
+// ignore-tidy-undocumented-unsafe
+
+use crate::cmp;
+use crate::fmt;
+use crate::mem;
+use crate::num::NonZeroUsize;
+use crate::ptr::NonNull;
+
+const fn size_align<T>() -> (usize, usize) {
+    (mem::size_of::<T>(), mem::align_of::<T>())
+}
+
+/// Layout of a block of memory.
+///
+/// An instance of `Layout` describes a particular layout of memory.
+/// You build a `Layout` up as an input to give to an allocator.
+///
+/// All layouts have an associated size and a power-of-two alignment.
+///
+/// (Note that layouts are *not* required to have non-zero size,
+/// even though `GlobalAlloc` requires that all memory requests
+/// be non-zero in size. A caller must either ensure that conditions
+/// like this are met, use specific allocators with looser
+/// requirements, or use the more lenient `AllocRef` interface.)
+#[stable(feature = "alloc_layout", since = "1.28.0")]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[lang = "alloc_layout"]
+pub struct Layout {
+    // size of the requested block of memory, measured in bytes.
+    size_: usize,
+
+    // alignment of the requested block of memory, measured in bytes.
+    // we ensure that this is always a power-of-two, because API's
+    // like `posix_memalign` require it and it is a reasonable
+    // constraint to impose on Layout constructors.
+    //
+    // (However, we do not analogously require `align >= sizeof(void*)`,
+    //  even though that is *also* a requirement of `posix_memalign`.)
+    align_: NonZeroUsize,
+}
+
+impl Layout {
+    /// Constructs a `Layout` from a given `size` and `align`,
+    /// or returns `LayoutErr` if any of the following conditions
+    /// are not met:
+    ///
+    /// * `align` must not be zero,
+    ///
+    /// * `align` must be a power of two,
+    ///
+    /// * `size`, when rounded up to the nearest multiple of `align`,
+    ///    must not overflow (i.e., the rounded value must be less than
+    ///    or equal to `usize::MAX`).
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[inline]
+    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
+        if !align.is_power_of_two() {
+            return Err(LayoutErr { private: () });
+        }
+
+        // (power-of-two implies align != 0.)
+
+        // Rounded up size is:
+        //   size_rounded_up = (size + align - 1) & !(align - 1);
+        //
+        // We know from above that align != 0. If adding (align - 1)
+        // does not overflow, then rounding up will be fine.
+        //
+        // Conversely, &-masking with !(align - 1) will subtract off
+        // only low-order-bits. Thus if overflow occurs with the sum,
+        // the &-mask cannot subtract enough to undo that overflow.
+        //
+        // Above implies that checking for summation overflow is both
+        // necessary and sufficient.
+        if size > usize::MAX - (align - 1) {
+            return Err(LayoutErr { private: () });
+        }
+
+        unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
+    }
+
+    /// Creates a layout, bypassing all checks.
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe as it does not verify the preconditions from
+    /// [`Layout::from_size_align`](#method.from_size_align).
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
+    #[inline]
+    pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
+        Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
+    }
+
+    /// The minimum size in bytes for a memory block of this layout.
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[inline]
+    pub const fn size(&self) -> usize {
+        self.size_
+    }
+
+    /// The minimum byte alignment for a memory block of this layout.
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[inline]
+    pub const fn align(&self) -> usize {
+        self.align_.get()
+    }
+
+    /// Constructs a `Layout` suitable for holding a value of type `T`.
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
+    #[inline]
+    pub const fn new<T>() -> Self {
+        let (size, align) = size_align::<T>();
+        // Note that the align is guaranteed by rustc to be a power of two and
+        // the size+align combo is guaranteed to fit in our address space. As a
+        // result use the unchecked constructor here to avoid inserting code
+        // that panics if it isn't optimized well enough.
+        unsafe { Layout::from_size_align_unchecked(size, align) }
+    }
+
+    /// Produces layout describing a record that could be used to
+    /// allocate backing structure for `T` (which could be a trait
+    /// or other unsized type like a slice).
+    #[stable(feature = "alloc_layout", since = "1.28.0")]
+    #[inline]
+    pub fn for_value<T: ?Sized>(t: &T) -> Self {
+        let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
+        // See rationale in `new` for why this is using an unsafe variant below
+        debug_assert!(Layout::from_size_align(size, align).is_ok());
+        unsafe { Layout::from_size_align_unchecked(size, align) }
+    }
+
+    /// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
+    ///
+    /// Note that the pointer value may potentially represent a valid pointer,
+    /// which means this must not be used as a "not yet initialized"
+    /// sentinel value. Types that lazily allocate must track initialization by
+    /// some other means.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub const fn dangling(&self) -> NonNull<u8> {
+        // align is non-zero and a power of two
+        unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
+    }
+
+    /// Creates a layout describing the record that can hold a value
+    /// of the same layout as `self`, but that also is aligned to
+    /// alignment `align` (measured in bytes).
+    ///
+    /// If `self` already meets the prescribed alignment, then returns
+    /// `self`.
+    ///
+    /// Note that this method does not add any padding to the overall
+    /// size, regardless of whether the returned layout has a different
+    /// alignment. In other words, if `K` has size 16, `K.align_to(32)`
+    /// will *still* have size 16.
+    ///
+    /// Returns an error if the combination of `self.size()` and the given
+    /// `align` violates the conditions listed in
+    /// [`Layout::from_size_align`](#method.from_size_align).
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
+        Layout::from_size_align(self.size(), cmp::max(self.align(), align))
+    }
+
+    /// Returns the amount of padding we must insert after `self`
+    /// to ensure that the following address will satisfy `align`
+    /// (measured in bytes).
+    ///
+    /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
+    /// returns 3, because that is the minimum number of bytes of
+    /// padding required to get a 4-aligned address (assuming that the
+    /// corresponding memory block starts at a 4-aligned address).
+    ///
+    /// The return value of this function has no meaning if `align` is
+    /// not a power-of-two.
+    ///
+    /// Note that the utility of the returned value requires `align`
+    /// to be less than or equal to the alignment of the starting
+    /// address for the whole allocated block of memory. One way to
+    /// satisfy this constraint is to ensure `align <= self.align()`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[inline]
+    pub const fn padding_needed_for(&self, align: usize) -> usize {
+        let len = self.size();
+
+        // Rounded up value is:
+        //   len_rounded_up = (len + align - 1) & !(align - 1);
+        // and then we return the padding difference: `len_rounded_up - len`.
+        //
+        // We use modular arithmetic throughout:
+        //
+        // 1. align is guaranteed to be > 0, so align - 1 is always
+        //    valid.
+        //
+        // 2. `len + align - 1` can overflow by at most `align - 1`,
+        //    so the &-mask with `!(align - 1)` will ensure that in the
+        //    case of overflow, `len_rounded_up` will itself be 0.
+        //    Thus the returned padding, when added to `len`, yields 0,
+        //    which trivially satisfies the alignment `align`.
+        //
+        // (Of course, attempts to allocate blocks of memory whose
+        // size and padding overflow in the above manner should cause
+        // the allocator to yield an error anyway.)
+
+        let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
+        len_rounded_up.wrapping_sub(len)
+    }
+
+    /// Creates a layout by rounding the size of this layout up to a multiple
+    /// of the layout's alignment.
+    ///
+    /// This is equivalent to adding the result of `padding_needed_for`
+    /// to the layout's current size.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn pad_to_align(&self) -> Layout {
+        let pad = self.padding_needed_for(self.align());
+        // This cannot overflow. Quoting from the invariant of Layout:
+        // > `size`, when rounded up to the nearest multiple of `align`,
+        // > must not overflow (i.e., the rounded value must be less than
+        // > `usize::MAX`)
+        let new_size = self.size() + pad;
+
+        Layout::from_size_align(new_size, self.align()).unwrap()
+    }
+
+    /// Creates a layout describing the record for `n` instances of
+    /// `self`, with a suitable amount of padding between each to
+    /// ensure that each instance is given its requested size and
+    /// alignment. On success, returns `(k, offs)` where `k` is the
+    /// layout of the array and `offs` is the distance between the start
+    /// of each element in the array.
+    ///
+    /// On arithmetic overflow, returns `LayoutErr`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
+        // This cannot overflow. Quoting from the invariant of Layout:
+        // > `size`, when rounded up to the nearest multiple of `align`,
+        // > must not overflow (i.e., the rounded value must be less than
+        // > `usize::MAX`)
+        let padded_size = self.size() + self.padding_needed_for(self.align());
+        let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
+
+        unsafe {
+            // self.align is already known to be valid and alloc_size has been
+            // padded already.
+            Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size))
+        }
+    }
+
+    /// Creates a layout describing the record for `self` followed by
+    /// `next`, including any necessary padding to ensure that `next`
+    /// will be properly aligned. Note that the resulting layout will
+    /// satisfy the alignment properties of both `self` and `next`.
+    ///
+    /// The resulting layout will be the same as that of a C struct containing
+    /// two fields with the layouts of `self` and `next`, in that order.
+    ///
+    /// Returns `Some((k, offset))`, where `k` is layout of the concatenated
+    /// record and `offset` is the relative location, in bytes, of the
+    /// start of the `next` embedded within the concatenated record
+    /// (assuming that the record itself starts at offset 0).
+    ///
+    /// On arithmetic overflow, returns `LayoutErr`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
+        let new_align = cmp::max(self.align(), next.align());
+        let pad = self.padding_needed_for(next.align());
+
+        let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
+        let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
+
+        let layout = Layout::from_size_align(new_size, new_align)?;
+        Ok((layout, offset))
+    }
+
+    /// Creates a layout describing the record for `n` instances of
+    /// `self`, with no padding between each instance.
+    ///
+    /// Note that, unlike `repeat`, `repeat_packed` does not guarantee
+    /// that the repeated instances of `self` will be properly
+    /// aligned, even if a given instance of `self` is properly
+    /// aligned. In other words, if the layout returned by
+    /// `repeat_packed` is used to allocate an array, it is not
+    /// guaranteed that all elements in the array will be properly
+    /// aligned.
+    ///
+    /// On arithmetic overflow, returns `LayoutErr`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
+        let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
+        Layout::from_size_align(size, self.align())
+    }
+
+    /// Creates a layout describing the record for `self` followed by
+    /// `next` with no additional padding between the two. Since no
+    /// padding is inserted, the alignment of `next` is irrelevant,
+    /// and is not incorporated *at all* into the resulting layout.
+    ///
+    /// On arithmetic overflow, returns `LayoutErr`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
+        let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
+        Layout::from_size_align(new_size, self.align())
+    }
+
+    /// Creates a layout describing the record for a `[T; n]`.
+    ///
+    /// On arithmetic overflow, returns `LayoutErr`.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
+        Layout::new::<T>().repeat(n).map(|(k, offs)| {
+            debug_assert!(offs == mem::size_of::<T>());
+            k
+        })
+    }
+}
+
+/// The parameters given to `Layout::from_size_align`
+/// or some other `Layout` constructor
+/// do not satisfy its documented constraints.
+#[stable(feature = "alloc_layout", since = "1.28.0")]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct LayoutErr {
+    private: (),
+}
+
+// (we need this for downstream impl of trait Error)
+#[stable(feature = "alloc_layout", since = "1.28.0")]
+impl fmt::Display for LayoutErr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("invalid parameters to Layout::from_size_align")
+    }
+}
diff --git a/src/libcore/alloc/mod.rs b/src/libcore/alloc/mod.rs
new file mode 100644
index 00000000000..e1892edb7c7
--- /dev/null
+++ b/src/libcore/alloc/mod.rs
@@ -0,0 +1,367 @@
+//! Memory allocation APIs
+
+#![stable(feature = "alloc_module", since = "1.28.0")]
+
+mod global;
+mod layout;
+
+#[stable(feature = "global_alloc", since = "1.28.0")]
+pub use self::global::GlobalAlloc;
+#[stable(feature = "alloc_layout", since = "1.28.0")]
+pub use self::layout::{Layout, LayoutErr};
+
+use crate::fmt;
+use crate::ptr::{self, NonNull};
+
+/// The `AllocErr` error indicates an allocation failure
+/// that may be due to resource exhaustion or to
+/// something wrong when combining the given input arguments with this
+/// allocator.
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AllocErr;
+
+// (we need this for downstream impl of trait Error)
+#[unstable(feature = "allocator_api", issue = "32838")]
+impl fmt::Display for AllocErr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("memory allocation failed")
+    }
+}
+
+/// A desired initial state for allocated memory.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[unstable(feature = "allocator_api", issue = "32838")]
+pub enum AllocInit {
+    /// The contents of the new memory are uninitialized.
+    Uninitialized,
+    /// The new memory is guaranteed to be zeroed.
+    Zeroed,
+}
+
+impl AllocInit {
+    /// Initialize the specified memory block.
+    ///
+    /// This behaves like calling [`AllocInit::init_offset(memory, 0)`][off].
+    ///
+    /// [off]: AllocInit::init_offset
+    ///
+    /// # Safety
+    ///
+    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
+    ///
+    /// [valid]: ../../core/ptr/index.html#safety
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub unsafe fn init(self, memory: MemoryBlock) {
+        self.init_offset(memory, 0)
+    }
+
+    /// Initialize the memory block like specified by `init` at the specified `offset`.
+    ///
+    /// This is a no-op for [`AllocInit::Uninitialized`][] and writes zeroes for
+    /// [`AllocInit::Zeroed`][] at `ptr + offset` until `ptr + layout.size()`.
+    ///
+    /// # Safety
+    ///
+    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
+    /// * `offset` must be smaller than or equal to `memory.size`
+    ///
+    /// [valid]: ../../core/ptr/index.html#safety
+    #[inline]
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub unsafe fn init_offset(self, memory: MemoryBlock, offset: usize) {
+        debug_assert!(
+            offset <= memory.size,
+            "`offset` must be smaller than or equal to `memory.size`"
+        );
+        match self {
+            AllocInit::Uninitialized => (),
+            AllocInit::Zeroed => {
+                memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset)
+            }
+        }
+    }
+}
+
+/// Represents a block of allocated memory returned by an allocator.
+#[derive(Debug, Copy, Clone)]
+#[unstable(feature = "allocator_api", issue = "32838")]
+pub struct MemoryBlock {
+    pub ptr: NonNull<u8>,
+    pub size: usize,
+}
+
+/// A placement constraint when growing or shrinking an existing allocation.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[unstable(feature = "allocator_api", issue = "32838")]
+pub enum ReallocPlacement {
+    /// The allocator is allowed to move the allocation to a different memory address.
+    // FIXME(wg-allocators#46): Add a section to the module documentation "What is a legal
+    //                          allocator" and link it at "valid location".
+    ///
+    /// If the allocation _does_ move, it's the responsibility of the allocator
+    /// to also move the data from the previous location to the new location.
+    MayMove,
+    /// The address of the new memory must not change.
+    ///
+    /// If the allocation would have to be moved to a new location to fit, the
+    /// reallocation request will fail.
+    InPlace,
+}
+
+/// An implementation of `AllocRef` can allocate, grow, shrink, and deallocate arbitrary blocks of
+/// data described via [`Layout`][].
+///
+/// `AllocRef` is designed to be implemented on ZSTs, references, or smart pointers because having
+/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
+/// allocated memory.
+///
+/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `AllocRef`. If an underlying
+/// allocator does not support this (like jemalloc) or return a null pointer (such as
+/// `libc::malloc`), this must be caught by the implementation.
+///
+/// ### Currently allocated memory
+///
+/// Some of the methods require that a memory block be *currently allocated* via an allocator. This
+/// means that:
+///
+/// * the starting address for that memory block was previously returned by [`alloc`], [`grow`], or
+///   [`shrink`], and
+///
+/// * the memory block has not been subsequently deallocated, where blocks are either deallocated
+///   directly by being passed to [`dealloc`] or were changed by being passed to [`grow`] or
+///   [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer
+///   remains valid.
+///
+/// [`alloc`]: AllocRef::alloc
+/// [`grow`]: AllocRef::grow
+/// [`shrink`]: AllocRef::shrink
+/// [`dealloc`]: AllocRef::dealloc
+///
+/// ### Memory fitting
+///
+/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to
+/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the
+/// following conditions must hold:
+///
+/// * The block must be allocated with the same alignment as [`layout.align()`], and
+///
+/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where:
+///   - `min` is the size of the layout most recently used to allocate the block, and
+///   - `max` is the latest actual size returned from [`alloc`], [`grow`], or [`shrink`].
+///
+/// [`layout.align()`]: Layout::align
+/// [`layout.size()`]: Layout::size
+///
+/// # Safety
+///
+/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
+///   until the instance and all of its clones are dropped,
+///
+/// * cloning or moving the allocator must not invalidate memory blocks returned from this
+///   allocator. A cloned allocator must behave like the same allocator, and
+///
+/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other
+///   method of the allocator.
+///
+/// [*currently allocated*]: #currently-allocated-memory
+#[unstable(feature = "allocator_api", issue = "32838")]
+pub unsafe trait AllocRef {
+    /// Attempts to allocate a block of memory.
+    ///
+    /// On success, returns a [`MemoryBlock`][] meeting the size and alignment guarantees of `layout`.
+    ///
+    /// The returned block may have a larger size than specified by `layout.size()` and is
+    /// initialized as specified by [`init`], all the way up to the returned size of the block.
+    ///
+    /// [`init`]: AllocInit
+    ///
+    /// # Errors
+    ///
+    /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
+    /// allocator's size or alignment constraints.
+    ///
+    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
+    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
+    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
+    ///
+    /// Clients wishing to abort computation in response to an allocation error are encouraged to
+    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr>;
+
+    /// Deallocates the memory referenced by `ptr`.
+    ///
+    /// # Safety
+    ///
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and
+    /// * `layout` must [*fit*] that block of memory.
+    ///
+    /// [*currently allocated*]: #currently-allocated-memory
+    /// [*fit*]: #memory-fitting
+    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
+
+    /// Attempts to extend the memory block.
+    ///
+    /// Returns a new [`MemoryBlock`][] containing a pointer and the actual size of the allocated
+    /// memory. The pointer is suitable for holding data described by a new layout with `layout`’s
+    /// alignment and a size given by `new_size`. To accomplish this, the allocator may extend the
+    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
+    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
+    ///
+    /// If [`MayMove`] is used then ownership of the memory block referenced by `ptr`
+    /// is transferred to this allocator. The memory may or may not be freed, and should be
+    /// considered unusable (unless of course it is transferred back to the caller again via the
+    /// return value of this method).
+    ///
+    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
+    /// this allocator, and the contents of the memory block are unaltered.
+    ///
+    /// The memory block will contain the following contents after a successful call to `grow`:
+    ///   * Bytes `0..layout.size()` are preserved from the original allocation.
+    ///   * Bytes `layout.size()..old_size` will either be preserved or initialized according to
+    ///     [`init`], depending on the allocator implementation. `old_size` refers to the size of
+    ///     the `MemoryBlock` prior to the `grow` call, which may be larger than the size
+    ///     that was originally requested when it was allocated.
+    ///   * Bytes `old_size..new_size` are initialized according to [`init`]. `new_size` refers to
+    ///     the size of the `MemoryBlock` returned by the `grow` call.
+    ///
+    /// [`InPlace`]: ReallocPlacement::InPlace
+    /// [`MayMove`]: ReallocPlacement::MayMove
+    /// [`placement`]: ReallocPlacement
+    /// [`init`]: AllocInit
+    ///
+    /// # Safety
+    ///
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
+    /// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.),
+    // We can't require that `new_size` is strictly greater than `memory.size` because of ZSTs.
+    // An alternative would be
+    // * `new_size must be strictly greater than `memory.size` or both are zero
+    /// * `new_size` must be greater than or equal to `layout.size()`, and
+    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
+    ///   (i.e., the rounded value must be less than or equal to `usize::MAX`).
+    ///
+    /// [*currently allocated*]: #currently-allocated-memory
+    /// [*fit*]: #memory-fitting
+    ///
+    /// # Errors
+    ///
+    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
+    /// constraints of the allocator, or if growing otherwise fails.
+    ///
+    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
+    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
+    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
+    ///
+    /// Clients wishing to abort computation in response to an allocation error are encouraged to
+    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    unsafe fn grow(
+        &mut self,
+        ptr: NonNull<u8>,
+        layout: Layout,
+        new_size: usize,
+        placement: ReallocPlacement,
+        init: AllocInit,
+    ) -> Result<MemoryBlock, AllocErr> {
+        match placement {
+            ReallocPlacement::InPlace => Err(AllocErr),
+            ReallocPlacement::MayMove => {
+                let size = layout.size();
+                debug_assert!(
+                    new_size >= size,
+                    "`new_size` must be greater than or equal to `layout.size()`"
+                );
+
+                if new_size == size {
+                    return Ok(MemoryBlock { ptr, size });
+                }
+
+                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+                let new_memory = self.alloc(new_layout, init)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size);
+                self.dealloc(ptr, layout);
+                Ok(new_memory)
+            }
+        }
+    }
+
+    /// Attempts to shrink the memory block.
+    ///
+    /// Returns a new [`MemoryBlock`][] containing a pointer and the actual size of the allocated
+    /// memory. The pointer is suitable for holding data described by a new layout with `layout`’s
+    /// alignment and a size given by `new_size`. To accomplish this, the allocator may shrink the
+    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
+    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
+    ///
+    /// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
+    /// transferred to this allocator. The memory may or may not have been freed, and should be
+    /// considered unusable unless it was transferred back to the caller again via the
+    /// return value of this method.
+    ///
+    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
+    /// this allocator, and the contents of the memory block are unaltered.
+    ///
+    /// The behavior of how the allocator tries to shrink the memory is specified by [`placement`].
+    ///
+    /// [`InPlace`]: ReallocPlacement::InPlace
+    /// [`placement`]: ReallocPlacement
+    ///
+    /// # Safety
+    ///
+    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
+    /// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.), and
+    // We can't require that `new_size` is strictly smaller than `memory.size` because of ZSTs.
+    // An alternative would be
+    // * `new_size must be strictly smaller than `memory.size` or both are zero
+    /// * `new_size` must be smaller than or equal to `layout.size()`.
+    ///
+    /// [*currently allocated*]: #currently-allocated-memory
+    /// [*fit*]: #memory-fitting
+    ///
+    /// # Errors
+    ///
+    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
+    /// constraints of the allocator, or if shrinking otherwise fails.
+    ///
+    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
+    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
+    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
+    ///
+    /// Clients wishing to abort computation in response to an allocation error are encouraged to
+    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
+    ///
+    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
+    unsafe fn shrink(
+        &mut self,
+        ptr: NonNull<u8>,
+        layout: Layout,
+        new_size: usize,
+        placement: ReallocPlacement,
+    ) -> Result<MemoryBlock, AllocErr> {
+        match placement {
+            ReallocPlacement::InPlace => Err(AllocErr),
+            ReallocPlacement::MayMove => {
+                let size = layout.size();
+                debug_assert!(
+                    new_size <= size,
+                    "`new_size` must be smaller than or equal to `layout.size()`"
+                );
+
+                if new_size == size {
+                    return Ok(MemoryBlock { ptr, size });
+                }
+
+                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+                let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?;
+                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size);
+                self.dealloc(ptr, layout);
+                Ok(new_memory)
+            }
+        }
+    }
+}
diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs
index 80eaae0d4af..f6b8d4ba081 100644
--- a/src/libcore/array/iter.rs
+++ b/src/libcore/array/iter.rs
@@ -39,7 +39,7 @@ where
     alive: Range<usize>,
 }
 
-impl<T, const N: usize> IntoIter<T, { N }>
+impl<T, const N: usize> IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -99,7 +99,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Iterator for IntoIter<T, { N }>
+impl<T, const N: usize> Iterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -146,7 +146,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, { N }>
+impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -182,7 +182,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Drop for IntoIter<T, { N }>
+impl<T, const N: usize> Drop for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -195,7 +195,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> ExactSizeIterator for IntoIter<T, { N }>
+impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -210,17 +210,17 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> FusedIterator for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
+impl<T, const N: usize> FusedIterator for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
 
 // The iterator indeed reports the correct length. The number of "alive"
 // elements (that will still be yielded) is the length of the range `alive`.
 // This range is decremented in length in either `next` or `next_back`. It is
 // always decremented by 1 in those methods, but only if `Some(_)` is returned.
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
+unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: Clone, const N: usize> Clone for IntoIter<T, { N }>
+impl<T: Clone, const N: usize> Clone for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
@@ -249,7 +249,7 @@ where
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, { N }>
+impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N>
 where
     [T; N]: LengthAtMost32,
 {
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index eb101fc72fd..6165941eb3d 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -169,7 +169,8 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
 /// Implementations of `Clone` for primitive types.
 ///
 /// Implementations that cannot be described in Rust
-/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
+/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
+/// in `rustc_trait_selection`.
 mod impls {
 
     use super::Clone;
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 604be7d5f68..8c542136a7f 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -817,7 +817,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// When comparison is impossible:
     ///
     /// ```
-    /// let result = std::f64::NAN.partial_cmp(&1.0);
+    /// let result = f64::NAN.partial_cmp(&1.0);
     /// assert_eq!(result, None);
     /// ```
     #[must_use]
diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs
index 47ab8715cfa..eef9ee7cb00 100644
--- a/src/libcore/convert/mod.rs
+++ b/src/libcore/convert/mod.rs
@@ -41,6 +41,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::fmt;
+use crate::hash::{Hash, Hasher};
 
 mod num;
 
@@ -746,3 +747,10 @@ impl From<!> for Infallible {
         x
     }
 }
+
+#[stable(feature = "convert_infallible_hash", since = "1.44.0")]
+impl Hash for Infallible {
+    fn hash<H: Hasher>(&self, _: &mut H) {
+        match *self {}
+    }
+}
diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs
index 752199c94b8..66ae760fc1f 100644
--- a/src/libcore/convert/num.rs
+++ b/src/libcore/convert/num.rs
@@ -13,9 +13,9 @@ mod private {
 /// Typically doesn’t need to be used directly.
 #[unstable(feature = "convert_float_to_int", issue = "67057")]
 pub trait FloatToInt<Int>: private::Sealed + Sized {
-    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[unstable(feature = "convert_float_to_int", issue = "67057")]
     #[doc(hidden)]
-    unsafe fn approx_unchecked(self) -> Int;
+    unsafe fn to_int_unchecked(self) -> Int;
 }
 
 macro_rules! impl_float_to_int {
@@ -27,8 +27,15 @@ macro_rules! impl_float_to_int {
             impl FloatToInt<$Int> for $Float {
                 #[doc(hidden)]
                 #[inline]
-                unsafe fn approx_unchecked(self) -> $Int {
-                    crate::intrinsics::float_to_int_approx_unchecked(self)
+                unsafe fn to_int_unchecked(self) -> $Int {
+                    #[cfg(bootstrap)]
+                    {
+                        crate::intrinsics::float_to_int_approx_unchecked(self)
+                    }
+                    #[cfg(not(bootstrap))]
+                    {
+                        crate::intrinsics::float_to_int_unchecked(self)
+                    }
                 }
             }
         )+
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index fe728d42c76..95411b525d0 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -852,7 +852,7 @@ pub trait LowerHex {
 ///     }
 /// }
 ///
-/// let l = Length(i32::max_value());
+/// let l = Length(i32::MAX);
 ///
 /// assert_eq!(format!("l as hex is: {:X}", l), "l as hex is: 7FFFFFFF");
 ///
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 698c97999c4..d406b3ce6ef 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -43,7 +43,7 @@ use crate::intrinsics;
 ///
 /// assert_eq!(div_1(7, 0), 7);
 /// assert_eq!(div_1(9, 1), 4);
-/// assert_eq!(div_1(11, std::u32::MAX), 0);
+/// assert_eq!(div_1(11, u32::MAX), 0);
 /// ```
 #[inline]
 #[stable(feature = "unreachable", since = "1.27.0")]
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 0c956104221..4a11fb39389 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1582,8 +1582,16 @@ extern "rust-intrinsic" {
     /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
     /// (<https://github.com/rust-lang/rust/issues/10184>)
     /// This is under stabilization at <https://github.com/rust-lang/rust/issues/67058>
+    #[cfg(bootstrap)]
     pub fn float_to_int_approx_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
 
+    /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+    /// (<https://github.com/rust-lang/rust/issues/10184>)
+    ///
+    /// Stabilized as `f32::to_int_unchecked` and `f64::to_int_unchecked`.
+    #[cfg(not(bootstrap))]
+    pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+
     /// Returns the number of bits set in an integer type `T`
     ///
     /// The stabilized versions of this intrinsic are available on the integer
@@ -1731,11 +1739,11 @@ extern "rust-intrinsic" {
     pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
 
     /// Performs an exact division, resulting in undefined behavior where
-    /// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
+    /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
     pub fn exact_div<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked division, resulting in undefined behavior
-    /// where y = 0 or x = `T::min_value()` and y = -1
+    /// where y = 0 or x = `T::MIN` and y = -1
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `checked_div` method. For example,
@@ -1743,7 +1751,7 @@ extern "rust-intrinsic" {
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
-    /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
+    /// undefined behavior where y = 0 or x = `T::MIN` and y = -1
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `checked_rem` method. For example,
@@ -1769,17 +1777,17 @@ extern "rust-intrinsic" {
     pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked addition, resulting in
-    /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+    /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked subtraction, resulting in
-    /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+    /// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked multiplication, resulting in
-    /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+    /// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index daa880e7cd5..c8829817e19 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -198,7 +198,7 @@ pub trait Iterator {
     /// // and the maximum possible lower bound
     /// let iter = 0..;
     ///
-    /// assert_eq!((usize::max_value(), None), iter.size_hint());
+    /// assert_eq!((usize::MAX, None), iter.size_hint());
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -2920,7 +2920,7 @@ pub trait Iterator {
     /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
     /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
     ///
-    /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None);
+    /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
     /// ```
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn partial_cmp<I>(self, other: I) -> Option<Ordering>
@@ -3170,7 +3170,7 @@ pub trait Iterator {
     /// assert!(![1, 3, 2, 4].iter().is_sorted());
     /// assert!([0].iter().is_sorted());
     /// assert!(std::iter::empty::<i32>().is_sorted());
-    /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+    /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
     /// ```
     #[inline]
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
@@ -3197,7 +3197,7 @@ pub trait Iterator {
     /// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
     /// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
     /// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| a.partial_cmp(b)));
-    /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+    /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
     /// ```
     ///
     /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index f67762cd043..9c885ef99a9 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -1070,8 +1070,10 @@ pub(crate) mod builtin {
 
     /// Includes a utf8-encoded file as a string.
     ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
+    /// The file is located relative to the current file (similarly to how
+    /// modules are found). The provided path is interpreted in a platform-specific
+    /// way at compile time. So, for instance, an invocation with a Windows path
+    /// containing backslashes `\` would not compile correctly on Unix.
     ///
     /// This macro will yield an expression of type `&'static str` which is the
     /// contents of the file.
@@ -1108,8 +1110,10 @@ pub(crate) mod builtin {
 
     /// Includes a file as a reference to a byte array.
     ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
+    /// The file is located relative to the current file (similarly to how
+    /// modules are found). The provided path is interpreted in a platform-specific
+    /// way at compile time. So, for instance, an invocation with a Windows path
+    /// containing backslashes `\` would not compile correctly on Unix.
     ///
     /// This macro will yield an expression of type `&'static [u8; N]` which is
     /// the contents of the file.
@@ -1202,7 +1206,9 @@ pub(crate) mod builtin {
     /// Parses a file as an expression or an item according to the context.
     ///
     /// The file is located relative to the current file (similarly to how
-    /// modules are found).
+    /// modules are found). The provided path is interpreted in a platform-specific
+    /// way at compile time. So, for instance, an invocation with a Windows path
+    /// containing backslashes `\` would not compile correctly on Unix.
     ///
     /// Using this macro is often a bad idea, because if the file is
     /// parsed as an expression, it is going to be placed in the
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index b131cf84e18..35bceaa25c3 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -759,7 +759,8 @@ impl<T: ?Sized> Unpin for *mut T {}
 /// Implementations of `Copy` for primitive types.
 ///
 /// Implementations that cannot be described in Rust
-/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
+/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
+/// in `rustc_trait_selection`.
 mod copy_impls {
 
     use super::Copy;
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 3fdc2bae338..4ab82add32b 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -464,15 +464,13 @@ impl f32 {
     /// assuming that the value is finite and fits in that type.
     ///
     /// ```
-    /// #![feature(float_approx_unchecked_to)]
-    ///
     /// let value = 4.6_f32;
-    /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+    /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
     /// assert_eq!(rounded, 4);
     ///
     /// let value = -128.9_f32;
-    /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
-    /// assert_eq!(rounded, std::i8::MIN);
+    /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
+    /// assert_eq!(rounded, i8::MIN);
     /// ```
     ///
     /// # Safety
@@ -482,13 +480,13 @@ impl f32 {
     /// * Not be `NaN`
     /// * Not be infinite
     /// * Be representable in the return type `Int`, after truncating off its fractional part
-    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
     #[inline]
-    pub unsafe fn approx_unchecked_to<Int>(self) -> Int
+    pub unsafe fn to_int_unchecked<Int>(self) -> Int
     where
         Self: FloatToInt<Int>,
     {
-        FloatToInt::<Int>::approx_unchecked(self)
+        FloatToInt::<Int>::to_int_unchecked(self)
     }
 
     /// Raw transmutation to `u32`.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 129df937c0b..20818a9b750 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -478,15 +478,13 @@ impl f64 {
     /// assuming that the value is finite and fits in that type.
     ///
     /// ```
-    /// #![feature(float_approx_unchecked_to)]
-    ///
     /// let value = 4.6_f32;
-    /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+    /// let rounded = unsafe { value.to_int_unchecked::<u16>() };
     /// assert_eq!(rounded, 4);
     ///
     /// let value = -128.9_f32;
-    /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
-    /// assert_eq!(rounded, std::i8::MIN);
+    /// let rounded = unsafe { value.to_int_unchecked::<i8>() };
+    /// assert_eq!(rounded, i8::MIN);
     /// ```
     ///
     /// # Safety
@@ -496,13 +494,13 @@ impl f64 {
     /// * Not be `NaN`
     /// * Not be infinite
     /// * Be representable in the return type `Int`, after truncating off its fractional part
-    #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+    #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
     #[inline]
-    pub unsafe fn approx_unchecked_to<Int>(self) -> Int
+    pub unsafe fn to_int_unchecked<Int>(self) -> Int
     where
         Self: FloatToInt<Int>,
     {
-        FloatToInt::<Int>::approx_unchecked(self)
+        FloatToInt::<Int>::to_int_unchecked(self)
     }
 
     /// Raw transmutation to `u64`.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 853092dd85e..7ba4004d860 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -174,7 +174,7 @@ NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
 /// let zero = Wrapping(0u32);
 /// let one = Wrapping(1u32);
 ///
-/// assert_eq!(std::u32::MAX, (zero - one).0);
+/// assert_eq!(u32::MAX, (zero - one).0);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
@@ -4376,7 +4376,7 @@ impl u8 {
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_uppercase(&self) -> u8 {
-        // Unset the fith bit if this is a lowercase letter
+        // Unset the fifth bit if this is a lowercase letter
         *self & !((self.is_ascii_lowercase() as u8) << 5)
     }
 
@@ -4399,7 +4399,7 @@ impl u8 {
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_lowercase(&self) -> u8 {
-        // Set the fith bit if this is an uppercase letter
+        // Set the fifth bit if this is an uppercase letter
         *self | ((self.is_ascii_uppercase() as u8) << 5)
     }
 
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index adee8cea442..946a765e18f 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -139,10 +139,9 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
     /// ```
     /// #![feature(range_is_empty)]
     ///
-    /// use std::f32::NAN;
     /// assert!(!(3.0..5.0).is_empty());
-    /// assert!( (3.0..NAN).is_empty());
-    /// assert!( (NAN..5.0).is_empty());
+    /// assert!( (3.0..f32::NAN).is_empty());
+    /// assert!( (f32::NAN..5.0).is_empty());
     /// ```
     #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
     pub fn is_empty(&self) -> bool {
@@ -496,10 +495,9 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     /// ```
     /// #![feature(range_is_empty)]
     ///
-    /// use std::f32::NAN;
     /// assert!(!(3.0..=5.0).is_empty());
-    /// assert!( (3.0..=NAN).is_empty());
-    /// assert!( (NAN..=5.0).is_empty());
+    /// assert!( (3.0..=f32::NAN).is_empty());
+    /// assert!( (f32::NAN..=5.0).is_empty());
     /// ```
     ///
     /// This method returns `true` after iteration has finished:
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index a540016854d..52e224d2a02 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -659,8 +659,8 @@ impl<T: ?Sized> *const T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::max_value()`. It is permissible for the implementation to *always*
-    /// return `usize::max_value()`. Only your algorithm's performance can depend
+    /// `usize::MAX`. It is permissible for the implementation to *always*
+    /// return `usize::MAX`. Only your algorithm's performance can depend
     /// on getting a usable offset here, not its correctness.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index 01d830ca186..9f85d781d69 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -847,8 +847,8 @@ impl<T: ?Sized> *mut T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::max_value()`. It is permissible for the implementation to *always*
-    /// return `usize::max_value()`. Only your algorithm's performance can depend
+    /// `usize::MAX`. It is permissible for the implementation to *always*
+    /// return `usize::MAX`. Only your algorithm's performance can depend
     /// on getting a usable offset here, not its correctness.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index 75c329a7d6c..cb0fb8795e5 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -6,7 +6,8 @@
 //! They can be used as targets of transmutes in unsafe code for manipulating
 //! the raw representations directly.
 //!
-//! Their definition should always match the ABI defined in `rustc::back::abi`.
+//! Their definition should always match the ABI defined in
+//! `rustc_middle::ty::layout`.
 
 /// The representation of a trait object like `&SomeTrait`.
 ///
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 2140a7be9ef..9be52e2dfb0 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2588,7 +2588,7 @@ impl<T> [T] {
     /// assert!(![1, 3, 2, 4].is_sorted());
     /// assert!([0].is_sorted());
     /// assert!(empty.is_sorted());
-    /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+    /// assert!(![0.0, 1.0, f32::NAN].is_sorted());
     /// ```
     #[inline]
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 013ca182c13..dc7637cfdb9 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -9,7 +9,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use self::pattern::Pattern;
-use self::pattern::{DoubleEndedSearcher, ReverseSearcher, SearchStep, Searcher};
+use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
 
 use crate::char;
 use crate::fmt::{self, Write};
@@ -2642,7 +2642,7 @@ impl str {
     /// # Panics
     ///
     /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
+    /// past the end of the last code point of the string slice.
     ///
     /// # Examples
     ///
@@ -2683,7 +2683,7 @@ impl str {
     /// # Panics
     ///
     /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
+    /// past the end of the last code point of the string slice.
     ///
     /// # Examples
     ///
@@ -3986,26 +3986,15 @@ impl str {
     /// ```
     /// #![feature(str_strip)]
     ///
-    /// assert_eq!("foobar".strip_prefix("foo"), Some("bar"));
-    /// assert_eq!("foobar".strip_prefix("bar"), None);
+    /// assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar"));
+    /// assert_eq!("foo:bar".strip_prefix("bar"), None);
     /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo"));
     /// ```
     #[must_use = "this returns the remaining substring as a new slice, \
                   without modifying the original"]
     #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")]
     pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
-        let mut matcher = prefix.into_searcher(self);
-        if let SearchStep::Match(start, len) = matcher.next() {
-            debug_assert_eq!(
-                start, 0,
-                "The first search step from Searcher \
-                 must include the first character"
-            );
-            // SAFETY: `Searcher` is known to return valid indices.
-            unsafe { Some(self.get_unchecked(len..)) }
-        } else {
-            None
-        }
+        prefix.strip_prefix_of(self)
     }
 
     /// Returns a string slice with the suffix removed.
@@ -4020,8 +4009,8 @@ impl str {
     ///
     /// ```
     /// #![feature(str_strip)]
-    /// assert_eq!("barfoo".strip_suffix("foo"), Some("bar"));
-    /// assert_eq!("barfoo".strip_suffix("bar"), None);
+    /// assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar"));
+    /// assert_eq!("bar:foo".strip_suffix("bar"), None);
     /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo"));
     /// ```
     #[must_use = "this returns the remaining substring as a new slice, \
@@ -4032,19 +4021,7 @@ impl str {
         P: Pattern<'a>,
         <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
     {
-        let mut matcher = suffix.into_searcher(self);
-        if let SearchStep::Match(start, end) = matcher.next_back() {
-            debug_assert_eq!(
-                end,
-                self.len(),
-                "The first search step from ReverseSearcher \
-                 must include the last character"
-            );
-            // SAFETY: `Searcher` is known to return valid indices.
-            unsafe { Some(self.get_unchecked(..start)) }
-        } else {
-            None
-        }
+        suffix.strip_suffix_of(self)
     }
 
     /// Returns a string slice with all suffixes that match a pattern
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index ffa418cba6c..30fd55f7b7f 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -47,6 +47,22 @@ pub trait Pattern<'a>: Sized {
         matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
     }
 
+    /// Removes the pattern from the front of haystack, if it matches.
+    #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if let SearchStep::Match(start, len) = self.into_searcher(haystack).next() {
+            debug_assert_eq!(
+                start, 0,
+                "The first search step from Searcher \
+                 must include the first character"
+            );
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(haystack.get_unchecked(len..)) }
+        } else {
+            None
+        }
+    }
+
     /// Checks whether the pattern matches at the back of the haystack
     #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool
@@ -55,6 +71,26 @@ pub trait Pattern<'a>: Sized {
     {
         matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
     }
+
+    /// Removes the pattern from the back of haystack, if it matches.
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+    where
+        Self::Searcher: ReverseSearcher<'a>,
+    {
+        if let SearchStep::Match(start, end) = self.into_searcher(haystack).next_back() {
+            debug_assert_eq!(
+                end,
+                haystack.len(),
+                "The first search step from ReverseSearcher \
+                 must include the last character"
+            );
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(haystack.get_unchecked(..start)) }
+        } else {
+            None
+        }
+    }
 }
 
 // Searcher
@@ -449,12 +485,25 @@ impl<'a> Pattern<'a> for char {
     }
 
     #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        self.encode_utf8(&mut [0u8; 4]).strip_prefix_of(haystack)
+    }
+
+    #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool
     where
         Self::Searcher: ReverseSearcher<'a>,
     {
         self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack)
     }
+
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+    where
+        Self::Searcher: ReverseSearcher<'a>,
+    {
+        self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack)
+    }
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -570,12 +619,25 @@ macro_rules! pattern_methods {
         }
 
         #[inline]
+        fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+            ($pmap)(self).strip_prefix_of(haystack)
+        }
+
+        #[inline]
         fn is_suffix_of(self, haystack: &'a str) -> bool
         where
             $t: ReverseSearcher<'a>,
         {
             ($pmap)(self).is_suffix_of(haystack)
         }
+
+        #[inline]
+        fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+        where
+            $t: ReverseSearcher<'a>,
+        {
+            ($pmap)(self).strip_suffix_of(haystack)
+        }
     };
 }
 
@@ -715,11 +777,34 @@ impl<'a, 'b> Pattern<'a> for &'b str {
         haystack.as_bytes().starts_with(self.as_bytes())
     }
 
+    /// Removes the pattern from the front of haystack, if it matches.
+    #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if self.is_prefix_of(haystack) {
+            // SAFETY: prefix was just verified to exist.
+            unsafe { Some(haystack.get_unchecked(self.as_bytes().len()..)) }
+        } else {
+            None
+        }
+    }
+
     /// Checks whether the pattern matches at the back of the haystack
     #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool {
         haystack.as_bytes().ends_with(self.as_bytes())
     }
+
+    /// Removes the pattern from the back of haystack, if it matches.
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if self.is_suffix_of(haystack) {
+            let i = haystack.len() - self.as_bytes().len();
+            // SAFETY: suffix was just verified to exist.
+            unsafe { Some(haystack.get_unchecked(..i)) }
+        } else {
+            None
+        }
+    }
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index 2ece2150e6b..924a64847a7 100644
--- a/src/libcore/time.rs
+++ b/src/libcore/time.rs
@@ -389,7 +389,7 @@ impl Duration {
     /// use std::time::Duration;
     ///
     /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
-    /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
+    /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
     /// ```
     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
     #[inline]
@@ -460,7 +460,7 @@ impl Duration {
     /// use std::time::Duration;
     ///
     /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
-    /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
+    /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
     /// ```
     #[stable(feature = "duration_checked_ops", since = "1.16.0")]
     #[inline]