about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs117
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs10
-rw-r--r--library/alloc/src/collections/vec_deque.rs4
-rw-r--r--library/alloc/src/vec.rs6
-rw-r--r--library/core/src/array/mod.rs13
-rw-r--r--library/core/src/iter/adapters/mod.rs38
-rw-r--r--library/core/src/iter/mod.rs56
-rw-r--r--library/core/src/iter/traits/double_ended.rs7
-rw-r--r--library/core/src/iter/traits/iterator.rs122
-rw-r--r--library/core/src/marker.rs59
-rw-r--r--library/core/src/ops/control_flow.rs67
-rw-r--r--library/core/src/ops/mod.rs4
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/option.rs1
-rw-r--r--library/core/tests/result.rs1
-rw-r--r--library/std/src/io/util.rs13
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/net/ip.rs59
-rw-r--r--library/std/src/primitive_docs.rs6
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/test/mir-opt/inline/inline-async.rs18
-rw-r--r--src/test/ui/consts/std/net/ipv4.rs58
25 files changed, 361 insertions, 300 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8262ae4cdbb..c044020d930 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1014,86 +1014,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
     }
 }
 
-// Because windows-gnu target is meant to be self-contained for pure Rust code it bundles
-// own mingw-w64 libraries. These libraries are usually not compatible with mingw-w64
-// installed in the system. This breaks many cases where Rust is mixed with other languages
-// (e.g. *-sys crates).
-// We prefer system mingw-w64 libraries if they are available to avoid this issue.
-fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
-    fn find_exe_in_path<P>(exe_name: P) -> Option<PathBuf>
-    where
-        P: AsRef<Path>,
-    {
-        for dir in env::split_paths(&env::var_os("PATH")?) {
-            let full_path = dir.join(&exe_name);
-            if full_path.is_file() {
-                return Some(fix_windows_verbatim_for_gcc(&full_path));
-            }
-        }
-        None
-    }
-
-    fn probe(sess: &Session) -> Option<PathBuf> {
-        if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) {
-            let linker_path = if cfg!(windows) && linker.extension().is_none() {
-                linker.with_extension("exe")
-            } else {
-                linker
-            };
-            if let Some(linker_path) = find_exe_in_path(linker_path) {
-                let mingw_arch = match &sess.target.target.arch {
-                    x if x == "x86" => "i686",
-                    x => x,
-                };
-                let mingw_bits = &sess.target.target.target_pointer_width;
-                let mingw_dir = format!("{}-w64-mingw32", mingw_arch);
-                // Here we have path/bin/gcc but we need path/
-                let mut path = linker_path;
-                path.pop();
-                path.pop();
-                // Loosely based on Clang MinGW driver
-                let probe_paths = vec![
-                    path.join(&mingw_dir).join("lib"),                // Typical path
-                    path.join(&mingw_dir).join("sys-root/mingw/lib"), // Rare path
-                    path.join(format!(
-                        "lib/mingw/tools/install/mingw{}/{}/lib",
-                        &mingw_bits, &mingw_dir
-                    )), // Chocolatey is creative
-                ];
-                for probe_path in probe_paths {
-                    if probe_path.join("crt2.o").exists() {
-                        return Some(probe_path);
-                    };
-                }
-            };
-        };
-        None
-    }
-
-    let mut system_library_path = sess.system_library_path.borrow_mut();
-    match &*system_library_path {
-        Some(Some(compiler_libs_path)) => Some(compiler_libs_path.clone()),
-        Some(None) => None,
-        None => {
-            let path = probe(sess);
-            *system_library_path = Some(path.clone());
-            path
-        }
-    }
-}
-
 fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
-    // prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
-    if sess.opts.cg.link_self_contained.is_none()
-        && sess.target.target.llvm_target.contains("windows-gnu")
-    {
-        if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
-            let file_path = compiler_libs_path.join(name);
-            if file_path.exists() {
-                return file_path;
-            }
-        }
-    }
     let fs = sess.target_filesearch(PathKind::Native);
     let file_path = fs.get_lib_path().join(name);
     if file_path.exists() {
@@ -1286,6 +1207,28 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
     }
 }
 
+// Returns true if linker is located within sysroot
+fn detect_self_contained_mingw(sess: &Session) -> bool {
+    let (linker, _) = linker_and_flavor(&sess);
+    // Assume `-C linker=rust-lld` as self-contained mode
+    if linker == Path::new("rust-lld") {
+        return true;
+    }
+    let linker_with_extension = if cfg!(windows) && linker.extension().is_none() {
+        linker.with_extension("exe")
+    } else {
+        linker
+    };
+    for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
+        let full_path = dir.join(&linker_with_extension);
+        // If linker comes from sysroot assume self-contained mode
+        if full_path.is_file() && !full_path.starts_with(&sess.sysroot) {
+            return false;
+        }
+    }
+    true
+}
+
 /// Whether we link to our own CRT objects instead of relying on gcc to pull them.
 /// We only provide such support for a very limited number of targets.
 fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
@@ -1298,10 +1241,10 @@ fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
         // based on host and linker path, for example.
         // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237).
         Some(CrtObjectsFallback::Musl) => sess.crt_static(Some(crate_type)),
-        // FIXME: Find some heuristic for "native mingw toolchain is available",
-        // likely based on `get_crt_libs_path` (https://github.com/rust-lang/rust/pull/67429).
         Some(CrtObjectsFallback::Mingw) => {
-            sess.host == sess.target.target && sess.target.target.target_vendor != "uwp"
+            sess.host == sess.target.target
+                && sess.target.target.target_vendor != "uwp"
+                && detect_self_contained_mingw(&sess)
         }
         // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
         Some(CrtObjectsFallback::Wasm) => true,
@@ -1498,16 +1441,6 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'
 
 /// Add sysroot and other globally set directories to the directory search list.
 fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
-    // Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details.
-    if sess.opts.cg.link_self_contained.is_none()
-        && cfg!(windows)
-        && sess.target.target.llvm_target.contains("windows-gnu")
-    {
-        if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
-            cmd.include_path(&compiler_libs_path);
-        }
-    }
-
     // The default library location, we need this to find the runtime.
     // The location of crates will be determined as needed.
     let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 315d4fa9d47..428f4e138c7 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -107,8 +107,14 @@ impl Inliner<'tcx> {
                     // Avoid a cycle here by only using `optimized_mir` only if we have
                     // a lower `HirId` than the callee. This ensures that the callee will
                     // not inline us. This trick only works without incremental compilation.
-                    // So don't do it if that is enabled.
-                    if !self.tcx.dep_graph.is_fully_enabled() && self_hir_id < callee_hir_id {
+                    // So don't do it if that is enabled. Also avoid inlining into generators,
+                    // since their `optimized_mir` is used for layout computation, which can
+                    // create a cycle, even when no attempt is made to inline the function
+                    // in the other direction.
+                    if !self.tcx.dep_graph.is_fully_enabled()
+                        && self_hir_id < callee_hir_id
+                        && caller_body.generator_kind.is_none()
+                    {
                         self.tcx.optimized_mir(callsite.callee)
                     } else {
                         continue;
diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs
index a4c6ccd6cb0..52b9f73ba88 100644
--- a/library/alloc/src/collections/vec_deque.rs
+++ b/library/alloc/src/collections/vec_deque.rs
@@ -685,7 +685,7 @@ impl<T> VecDeque<T> {
     }
 
     /// Tries to reserve the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `VecDeque<T>`. After calling `reserve_exact`,
+    /// be inserted in the given `VecDeque<T>`. After calling `try_reserve_exact`,
     /// capacity will be greater than or equal to `self.len() + additional`.
     /// Does nothing if the capacity is already sufficient.
     ///
@@ -727,7 +727,7 @@ impl<T> VecDeque<T> {
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
     /// in the given `VecDeque<T>`. The collection may reserve more space to avoid
-    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional`. Does nothing if
     /// capacity is already sufficient.
     ///
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index c86798a1bd3..27eefb05842 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -523,7 +523,7 @@ impl<T> Vec<T> {
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
     /// in the given `Vec<T>`. The collection may reserve more space to avoid
-    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional`. Does nothing if
     /// capacity is already sufficient.
     ///
@@ -559,7 +559,7 @@ impl<T> Vec<T> {
     }
 
     /// Tries to reserves the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `Vec<T>`. After calling `reserve_exact`,
+    /// be inserted in the given `Vec<T>`. After calling `try_reserve_exact`,
     /// capacity will be greater than or equal to `self.len() + additional`.
     /// Does nothing if the capacity is already sufficient.
     ///
@@ -582,7 +582,7 @@ impl<T> Vec<T> {
     ///     let mut output = Vec::new();
     ///
     ///     // Pre-reserve the memory, exiting if we can't
-    ///     output.try_reserve(data.len())?;
+    ///     output.try_reserve_exact(data.len())?;
     ///
     ///     // Now we know this can't OOM in the middle of our complex work
     ///     output.extend(data.iter().map(|&val| {
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index f85be5584e3..f45c99c285c 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -422,4 +422,17 @@ impl<T, const N: usize> [T; N] {
         // and we just need to cast it to the correct type.
         unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
     }
+
+    /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn as_slice(&self) -> &[T] {
+        self
+    }
+
+    /// Returns a mutable slice containing the entire array. Equivalent to
+    /// `&mut s[..]`.
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        self
+    }
 }
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index 9fcd137e1a6..f32c3963abe 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1,9 +1,9 @@
 use crate::cmp;
 use crate::fmt;
 use crate::intrinsics;
-use crate::ops::{Add, AddAssign, Try};
+use crate::ops::{Add, AddAssign, ControlFlow, Try};
 
-use super::{from_fn, LoopState};
+use super::from_fn;
 use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
 
 mod chain;
@@ -1164,10 +1164,10 @@ where
         #[inline]
         fn find<T, B>(
             f: &mut impl FnMut(T) -> Option<B>,
-        ) -> impl FnMut((), T) -> LoopState<(), B> + '_ {
+        ) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
             move |(), x| match f(x) {
-                Some(x) => LoopState::Break(x),
-                None => LoopState::Continue(()),
+                Some(x) => ControlFlow::Break(x),
+                None => ControlFlow::Continue(()),
             }
         }
 
@@ -1864,13 +1864,13 @@ where
             flag: &'a mut bool,
             p: &'a mut impl FnMut(&T) -> bool,
             mut fold: impl FnMut(Acc, T) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+        ) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
             move |acc, x| {
                 if p(&x) {
-                    LoopState::from_try(fold(acc, x))
+                    ControlFlow::from_try(fold(acc, x))
                 } else {
                     *flag = true;
-                    LoopState::Break(Try::from_ok(acc))
+                    ControlFlow::Break(Try::from_ok(acc))
                 }
             }
         }
@@ -1963,8 +1963,8 @@ where
     {
         let Self { iter, predicate } = self;
         iter.try_fold(init, |acc, x| match predicate(x) {
-            Some(item) => LoopState::from_try(fold(acc, item)),
-            None => LoopState::Break(Try::from_ok(acc)),
+            Some(item) => ControlFlow::from_try(fold(acc, item)),
+            None => ControlFlow::Break(Try::from_ok(acc)),
         })
         .into_try()
     }
@@ -2135,11 +2135,11 @@ where
         fn check<T, Acc, R: Try<Ok = Acc>>(
             mut n: usize,
             mut fold: impl FnMut(Acc, T) -> R,
-        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> {
+        ) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> {
             move |acc, x| {
                 n -= 1;
                 let r = fold(acc, x);
-                if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
+                if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
             }
         }
 
@@ -2246,11 +2246,11 @@ where
         fn check<'a, T, Acc, R: Try<Ok = Acc>>(
             n: &'a mut usize,
             mut fold: impl FnMut(Acc, T) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+        ) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
             move |acc, x| {
                 *n -= 1;
                 let r = fold(acc, x);
-                if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
+                if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
             }
         }
 
@@ -2414,10 +2414,10 @@ where
             state: &'a mut St,
             f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
             mut fold: impl FnMut(Acc, B) -> R + 'a,
-        ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
+        ) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
             move |acc, x| match f(state, x) {
-                None => LoopState::Break(Try::from_ok(acc)),
-                Some(x) => LoopState::from_try(fold(acc, x)),
+                None => ControlFlow::Break(Try::from_ok(acc)),
+                Some(x) => ControlFlow::from_try(fold(acc, x)),
             }
         }
 
@@ -2638,10 +2638,10 @@ where
         let error = &mut *self.error;
         self.iter
             .try_fold(init, |acc, x| match x {
-                Ok(x) => LoopState::from_try(f(acc, x)),
+                Ok(x) => ControlFlow::from_try(f(acc, x)),
                 Err(e) => {
                     *error = Err(e);
-                    LoopState::Break(Try::from_ok(acc))
+                    ControlFlow::Break(Try::from_ok(acc))
                 }
             })
             .into_try()
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 1be9c4de916..bab8dda2915 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -308,8 +308,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::ops::Try;
-
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::traits::Iterator;
 
@@ -367,57 +365,3 @@ mod adapters;
 mod range;
 mod sources;
 mod traits;
-
-/// Used to make try_fold closures more like normal loops
-#[derive(PartialEq)]
-enum LoopState<C, B> {
-    Continue(C),
-    Break(B),
-}
-
-impl<C, B> Try for LoopState<C, B> {
-    type Ok = C;
-    type Error = B;
-    #[inline]
-    fn into_result(self) -> Result<Self::Ok, Self::Error> {
-        match self {
-            LoopState::Continue(y) => Ok(y),
-            LoopState::Break(x) => Err(x),
-        }
-    }
-    #[inline]
-    fn from_error(v: Self::Error) -> Self {
-        LoopState::Break(v)
-    }
-    #[inline]
-    fn from_ok(v: Self::Ok) -> Self {
-        LoopState::Continue(v)
-    }
-}
-
-impl<C, B> LoopState<C, B> {
-    #[inline]
-    fn break_value(self) -> Option<B> {
-        match self {
-            LoopState::Continue(..) => None,
-            LoopState::Break(x) => Some(x),
-        }
-    }
-}
-
-impl<R: Try> LoopState<R::Ok, R> {
-    #[inline]
-    fn from_try(r: R) -> Self {
-        match Try::into_result(r) {
-            Ok(v) => LoopState::Continue(v),
-            Err(v) => LoopState::Break(Try::from_error(v)),
-        }
-    }
-    #[inline]
-    fn into_try(self) -> R {
-        match self {
-            LoopState::Continue(v) => Try::from_ok(v),
-            LoopState::Break(v) => v,
-        }
-    }
-}
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index 851a1e49a49..25230519f37 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -1,5 +1,4 @@
-use crate::iter::LoopState;
-use crate::ops::Try;
+use crate::ops::{ControlFlow, Try};
 
 /// An iterator able to yield elements from both ends.
 ///
@@ -309,9 +308,9 @@ pub trait DoubleEndedIterator: Iterator {
         #[inline]
         fn check<T>(
             mut predicate: impl FnMut(&T) -> bool,
-        ) -> impl FnMut((), T) -> LoopState<(), T> {
+        ) -> impl FnMut((), T) -> ControlFlow<(), T> {
             move |(), x| {
-                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
+                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
             }
         }
 
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 0bac21406bf..46ef12cd938 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3,9 +3,8 @@
 // can't split that into multiple files.
 
 use crate::cmp::{self, Ordering};
-use crate::ops::{Add, Try};
+use crate::ops::{Add, ControlFlow, Try};
 
-use super::super::LoopState;
 use super::super::TrustedRandomAccess;
 use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
 use super::super::{FlatMap, Flatten};
@@ -22,8 +21,8 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 /// generally, please see the [module-level documentation]. In particular, you
 /// may want to know how to [implement `Iterator`][impl].
 ///
-/// [module-level documentation]: index.html
-/// [impl]: index.html#implementing-iterator
+/// [module-level documentation]: crate::iter
+/// [impl]: crate::iter#implementing-iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
@@ -212,7 +211,7 @@ pub trait Iterator {
     /// returning the number of times it saw [`Some`]. Note that [`next`] has to be
     /// called at least once even if the iterator does not have any elements.
     ///
-    /// [`next`]: #tymethod.next
+    /// [`next`]: Iterator::next
     ///
     /// # Overflow Behavior
     ///
@@ -449,9 +448,7 @@ pub trait Iterator {
     /// }
     /// ```
     ///
-    /// [`once`]: fn.once.html
-    /// [`Iterator`]: trait.Iterator.html
-    /// [`IntoIterator`]: trait.IntoIterator.html
+    /// [`once`]: crate::iter::once
     /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -496,9 +493,6 @@ pub trait Iterator {
     /// [`Iterator`] itself. For example, slices (`&[T]`) implement
     /// [`IntoIterator`], and so can be passed to `zip()` directly:
     ///
-    /// [`IntoIterator`]: trait.IntoIterator.html
-    /// [`Iterator`]: trait.Iterator.html
-    ///
     /// ```
     /// let s1 = &[1, 2, 3];
     /// let s2 = &[4, 5, 6];
@@ -530,8 +524,8 @@ pub trait Iterator {
     /// assert_eq!((2, 'o'), zipper[2]);
     /// ```
     ///
-    /// [`enumerate`]: #method.enumerate
-    /// [`next`]: #tymethod.next
+    /// [`enumerate`]: Iterator::enumerate
+    /// [`next`]: Iterator::next
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
@@ -734,8 +728,8 @@ pub trait Iterator {
     /// Why `filter_map` and not just [`filter`] and [`map`]? The key is in this
     /// part:
     ///
-    /// [`filter`]: #method.filter
-    /// [`map`]: #method.map
+    /// [`filter`]: Iterator::filter
+    /// [`map`]: Iterator::map
     ///
     /// > If the closure returns [`Some(element)`][`Some`], then that element is returned.
     ///
@@ -802,7 +796,7 @@ pub trait Iterator {
     ///
     /// [`usize`]: type@usize
     /// [`usize::MAX`]: crate::usize::MAX
-    /// [`zip`]: #method.zip
+    /// [`zip`]: Iterator::zip
     ///
     /// # Examples
     ///
@@ -837,8 +831,8 @@ pub trait Iterator {
     /// anything other than fetching the next value) of the [`next`] method
     /// will occur.
     ///
-    /// [`peek`]: crate::iter::Peekable::peek
-    /// [`next`]: #tymethod.next
+    /// [`peek`]: Peekable::peek
+    /// [`next`]: Iterator::next
     ///
     /// # Examples
     ///
@@ -876,7 +870,7 @@ pub trait Iterator {
 
     /// Creates an iterator that [`skip`]s elements based on a predicate.
     ///
-    /// [`skip`]: #method.skip
+    /// [`skip`]: Iterator::skip
     ///
     /// `skip_while()` takes a closure as an argument. It will call this
     /// closure on each element of the iterator, and ignore elements
@@ -1043,8 +1037,8 @@ pub trait Iterator {
     ///
     /// Here's the same example, but with [`take_while`] and [`map`]:
     ///
-    /// [`take_while`]: #method.take_while
-    /// [`map`]: #method.map
+    /// [`take_while`]: Iterator::take_while
+    /// [`map`]: Iterator::map
     ///
     /// ```
     /// let a = [-1i32, 4, 0, 1];
@@ -1104,7 +1098,7 @@ pub trait Iterator {
     /// It is also not specified what this iterator returns after the first` None` is returned.
     /// If you need fused iterator, use [`fuse`].
     ///
-    /// [`fuse`]: #method.fuse
+    /// [`fuse`]: Iterator::fuse
     #[inline]
     #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
     fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
@@ -1190,7 +1184,7 @@ pub trait Iterator {
     /// An iterator adaptor similar to [`fold`] that holds internal state and
     /// produces a new iterator.
     ///
-    /// [`fold`]: #method.fold
+    /// [`fold`]: Iterator::fold
     ///
     /// `scan()` takes two arguments: an initial value which seeds the internal
     /// state, and a closure with two arguments, the first being a mutable
@@ -1246,8 +1240,8 @@ pub trait Iterator {
     /// one item for each element, and `flat_map()`'s closure returns an
     /// iterator for each element.
     ///
-    /// [`map`]: #method.map
-    /// [`flatten`]: #method.flatten
+    /// [`map`]: Iterator::map
+    /// [`flatten`]: Iterator::flatten
     ///
     /// # Examples
     ///
@@ -1333,7 +1327,7 @@ pub trait Iterator {
     /// two-dimensional and not one-dimensional. To get a one-dimensional
     /// structure, you have to `flatten()` again.
     ///
-    /// [`flat_map()`]: #method.flat_map
+    /// [`flat_map()`]: Iterator::flat_map
     #[inline]
     #[stable(feature = "iterator_flatten", since = "1.29.0")]
     fn flatten(self) -> Flatten<Self>
@@ -1640,7 +1634,7 @@ pub trait Iterator {
     /// assert_eq!(Ok(vec![1, 3]), result);
     /// ```
     ///
-    /// [`iter`]: #tymethod.next
+    /// [`iter`]: Iterator::next
     /// [`String`]: ../../std/string/struct.String.html
     /// [`char`]: type@char
     #[inline]
@@ -1661,8 +1655,8 @@ pub trait Iterator {
     ///
     /// See also [`is_partitioned()`] and [`partition_in_place()`].
     ///
-    /// [`is_partitioned()`]: #method.is_partitioned
-    /// [`partition_in_place()`]: #method.partition_in_place
+    /// [`is_partitioned()`]: Iterator::is_partitioned
+    /// [`partition_in_place()`]: Iterator::partition_in_place
     ///
     /// # Examples
     ///
@@ -1716,8 +1710,8 @@ pub trait Iterator {
     ///
     /// See also [`is_partitioned()`] and [`partition()`].
     ///
-    /// [`is_partitioned()`]: #method.is_partitioned
-    /// [`partition()`]: #method.partition
+    /// [`is_partitioned()`]: Iterator::is_partitioned
+    /// [`partition()`]: Iterator::partition
     ///
     /// # Examples
     ///
@@ -1779,8 +1773,8 @@ pub trait Iterator {
     ///
     /// See also [`partition()`] and [`partition_in_place()`].
     ///
-    /// [`partition()`]: #method.partition
-    /// [`partition_in_place()`]: #method.partition_in_place
+    /// [`partition()`]: Iterator::partition
+    /// [`partition_in_place()`]: Iterator::partition_in_place
     ///
     /// # Examples
     ///
@@ -1879,8 +1873,8 @@ pub trait Iterator {
     /// This can also be thought of as the fallible form of [`for_each()`]
     /// or as the stateless version of [`try_fold()`].
     ///
-    /// [`for_each()`]: #method.for_each
-    /// [`try_fold()`]: #method.try_fold
+    /// [`for_each()`]: Iterator::for_each
+    /// [`try_fold()`]: Iterator::try_fold
     ///
     /// # Examples
     ///
@@ -2006,11 +2000,13 @@ pub trait Iterator {
         accum
     }
 
-    /// The same as [`fold()`](#method.fold), but uses the first element in the
+    /// The same as [`fold()`], but uses the first element in the
     /// iterator as the initial value, folding every subsequent element into it.
     /// If the iterator is empty, return `None`; otherwise, return the result
     /// of the fold.
     ///
+    /// [`fold()`]: Iterator::fold
+    ///
     /// # Example
     ///
     /// Find the maximum value:
@@ -2088,12 +2084,12 @@ pub trait Iterator {
         F: FnMut(Self::Item) -> bool,
     {
         #[inline]
-        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
             move |(), x| {
-                if f(x) { LoopState::Continue(()) } else { LoopState::Break(()) }
+                if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
             }
         }
-        self.try_fold((), check(f)) == LoopState::Continue(())
+        self.try_fold((), check(f)) == ControlFlow::Continue(())
     }
 
     /// Tests if any element of the iterator matches a predicate.
@@ -2141,13 +2137,13 @@ pub trait Iterator {
         F: FnMut(Self::Item) -> bool,
     {
         #[inline]
-        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
             move |(), x| {
-                if f(x) { LoopState::Break(()) } else { LoopState::Continue(()) }
+                if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
             }
         }
 
-        self.try_fold((), check(f)) == LoopState::Break(())
+        self.try_fold((), check(f)) == ControlFlow::Break(())
     }
 
     /// Searches for an element of an iterator that satisfies a predicate.
@@ -2203,9 +2199,9 @@ pub trait Iterator {
         #[inline]
         fn check<T>(
             mut predicate: impl FnMut(&T) -> bool,
-        ) -> impl FnMut((), T) -> LoopState<(), T> {
+        ) -> impl FnMut((), T) -> ControlFlow<(), T> {
             move |(), x| {
-                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
+                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
             }
         }
 
@@ -2235,10 +2231,12 @@ pub trait Iterator {
         F: FnMut(Self::Item) -> Option<B>,
     {
         #[inline]
-        fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> LoopState<(), B> {
+        fn check<T, B>(
+            mut f: impl FnMut(T) -> Option<B>,
+        ) -> impl FnMut((), T) -> ControlFlow<(), B> {
             move |(), x| match f(x) {
-                Some(x) => LoopState::Break(x),
-                None => LoopState::Continue(()),
+                Some(x) => ControlFlow::Break(x),
+                None => ControlFlow::Continue(()),
             }
         }
 
@@ -2274,15 +2272,15 @@ pub trait Iterator {
         R: Try<Ok = bool>,
     {
         #[inline]
-        fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result<T, R::Error>>
+        fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<(), Result<T, R::Error>>
         where
             F: FnMut(&T) -> R,
             R: Try<Ok = bool>,
         {
             move |(), x| match f(&x).into_result() {
-                Ok(false) => LoopState::Continue(()),
-                Ok(true) => LoopState::Break(Ok(x)),
-                Err(x) => LoopState::Break(Err(x)),
+                Ok(false) => ControlFlow::Continue(()),
+                Ok(true) => ControlFlow::Break(Ok(x)),
+                Err(x) => ControlFlow::Break(Err(x)),
             }
         }
 
@@ -2352,10 +2350,14 @@ pub trait Iterator {
         #[inline]
         fn check<T>(
             mut predicate: impl FnMut(T) -> bool,
-        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+        ) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
             // The addition might panic on overflow
             move |i, x| {
-                if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(Add::add(i, 1)) }
+                if predicate(x) {
+                    ControlFlow::Break(i)
+                } else {
+                    ControlFlow::Continue(Add::add(i, 1))
+                }
             }
         }
 
@@ -2411,10 +2413,10 @@ pub trait Iterator {
         #[inline]
         fn check<T>(
             mut predicate: impl FnMut(T) -> bool,
-        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+        ) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
             move |i, x| {
                 let i = i - 1;
-                if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(i) }
+                if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) }
             }
         }
 
@@ -2602,8 +2604,6 @@ pub trait Iterator {
     /// This is only possible if the iterator has an end, so `rev()` only
     /// works on [`DoubleEndedIterator`]s.
     ///
-    /// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -2634,7 +2634,7 @@ pub trait Iterator {
     ///
     /// This function is, in some sense, the opposite of [`zip`].
     ///
-    /// [`zip`]: #method.zip
+    /// [`zip`]: Iterator::zip
     ///
     /// # Examples
     ///
@@ -2713,7 +2713,7 @@ pub trait Iterator {
     /// This is useful when you have an iterator over `&T`, but you need an
     /// iterator over `T`.
     ///
-    /// [`clone`]: crate::clone::Clone::clone
+    /// [`clone`]: Clone::clone
     ///
     /// # Examples
     ///
@@ -3201,7 +3201,7 @@ pub trait Iterator {
     /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
     /// ```
     ///
-    /// [`is_sorted`]: #method.is_sorted
+    /// [`is_sorted`]: Iterator::is_sorted
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
     fn is_sorted_by<F>(mut self, mut compare: F) -> bool
     where
@@ -3230,7 +3230,7 @@ pub trait Iterator {
     /// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see
     /// its documentation for more information.
     ///
-    /// [`is_sorted`]: #method.is_sorted
+    /// [`is_sorted`]: Iterator::is_sorted
     ///
     /// # Examples
     ///
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index a02ee9c5ba9..9340b591ebd 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -111,13 +111,13 @@ pub trait Sized {
 ///   - `T` is not part of the type of any other fields
 ///   - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
 ///
-/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow
-/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized
+/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
+/// "user-defined" containers such as [`Rc`] to contain dynamically-sized
 /// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce]
 /// for more details.
 ///
-/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
-/// [rc]: ../../std/rc/struct.Rc.html
+/// [`ops::CoerceUnsized`]: crate::ops::CoerceUnsized
+/// [`Rc`]: ../../std/rc/struct.Rc.html
 /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "unsize", issue = "27732")]
@@ -368,11 +368,7 @@ pub trait StructuralEq {
 ///
 /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
 /// [`String`]: ../../std/string/struct.String.html
-/// [`Drop`]: ../../std/ops/trait.Drop.html
-/// [`size_of::<T>`]: ../../std/mem/fn.size_of.html
-/// [`Clone`]: ../clone/trait.Clone.html
-/// [`String`]: ../../std/string/struct.String.html
-/// [`i32`]: ../../std/primitive.i32.html
+/// [`size_of::<T>`]: crate::mem::size_of
 /// [impls]: #implementors
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "copy"]
@@ -400,18 +396,18 @@ pub macro Copy($item:item) {
 /// This trait is automatically implemented when the compiler determines
 /// it's appropriate.
 ///
-/// The precise definition is: a type `T` is `Sync` if and only if `&T` is
-/// [`Send`][send]. In other words, if there is no possibility of
+/// The precise definition is: a type `T` is [`Sync`] if and only if `&T` is
+/// [`Send`]. In other words, if there is no possibility of
 /// [undefined behavior][ub] (including data races) when passing
 /// `&T` references between threads.
 ///
-/// As one would expect, primitive types like [`u8`][u8] and [`f64`][f64]
-/// are all `Sync`, and so are simple aggregate types containing them,
-/// like tuples, structs and enums. More examples of basic `Sync`
+/// As one would expect, primitive types like [`u8`] and [`f64`]
+/// are all [`Sync`], and so are simple aggregate types containing them,
+/// like tuples, structs and enums. More examples of basic [`Sync`]
 /// types include "immutable" types like `&T`, and those with simple
 /// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and
-/// most other collection types. (Generic parameters need to be `Sync`
-/// for their container to be `Sync`.)
+/// most other collection types. (Generic parameters need to be [`Sync`]
+/// for their container to be [`Sync`].)
 ///
 /// A somewhat surprising consequence of the definition is that `&mut T`
 /// is `Sync` (if `T` is `Sync`) even though it seems like that might
@@ -421,15 +417,15 @@ pub macro Copy($item:item) {
 /// of a data race.
 ///
 /// Types that are not `Sync` are those that have "interior
-/// mutability" in a non-thread-safe form, such as [`cell::Cell`][cell]
-/// and [`cell::RefCell`][refcell]. These types allow for mutation of
+/// mutability" in a non-thread-safe form, such as [`Cell`][cell]
+/// and [`RefCell`][refcell]. These types allow for mutation of
 /// their contents even through an immutable, shared reference. For
 /// example the `set` method on [`Cell<T>`][cell] takes `&self`, so it requires
 /// only a shared reference [`&Cell<T>`][cell]. The method performs no
 /// synchronization, thus [`Cell`][cell] cannot be `Sync`.
 ///
 /// Another example of a non-`Sync` type is the reference-counting
-/// pointer [`rc::Rc`][rc]. Given any reference [`&Rc<T>`][rc], you can clone
+/// pointer [`Rc`][rc]. Given any reference [`&Rc<T>`][rc], you can clone
 /// a new [`Rc<T>`][rc], modifying the reference counts in a non-atomic way.
 ///
 /// For cases when one does need thread-safe interior mutability,
@@ -445,24 +441,21 @@ pub macro Copy($item:item) {
 /// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing
 /// from `&T` to `&mut T` is invalid.
 ///
-/// See [the Nomicon](../../nomicon/send-and-sync.html) for more
-/// details about `Sync`.
+/// See [the Nomicon][nomicon-send-and-sync] for more details about `Sync`.
 ///
-/// [send]: trait.Send.html
-/// [u8]: ../../std/primitive.u8.html
-/// [f64]: ../../std/primitive.f64.html
 /// [box]: ../../std/boxed/struct.Box.html
 /// [vec]: ../../std/vec/struct.Vec.html
-/// [cell]: ../cell/struct.Cell.html
-/// [refcell]: ../cell/struct.RefCell.html
+/// [cell]: crate::cell::Cell
+/// [refcell]: crate::cell::RefCell
 /// [rc]: ../../std/rc/struct.Rc.html
 /// [arc]: ../../std/sync/struct.Arc.html
-/// [atomic data types]: ../sync/atomic/index.html
+/// [atomic data types]: crate::sync::atomic
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
-/// [unsafecell]: ../cell/struct.UnsafeCell.html
+/// [unsafecell]: crate::cell::UnsafeCell
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [transmute]: ../../std/mem/fn.transmute.html
+/// [transmute]: crate::mem::transmute
+/// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")]
 #[lang = "sync"]
@@ -698,7 +691,7 @@ mod impls {
 /// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute
 /// between `DiscriminantKind::Discriminant` and `mem::Discriminant`.
 ///
-/// [`mem::Discriminant`]: https://doc.rust-lang.org/stable/core/mem/struct.Discriminant.html
+/// [`mem::Discriminant`]: crate::mem::Discriminant
 #[unstable(
     feature = "discriminant_kind",
     issue = "none",
@@ -733,7 +726,7 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
 ///
 /// The [`Pin`][Pin] type is used instead to prevent moves through the type
 /// system. Pointers `P<T>` wrapped in the [`Pin<P<T>>`][Pin] wrapper can't be
-/// moved out of. See the [`pin module`] documentation for more information on
+/// moved out of. See the [`pin` module] documentation for more information on
 /// pinning.
 ///
 /// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off
@@ -764,9 +757,9 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
 ///
 /// This trait is automatically implemented for almost every type.
 ///
-/// [`mem::replace`]: ../../std/mem/fn.replace.html
+/// [`mem::replace`]: crate::mem::replace
 /// [Pin]: crate::pin::Pin
-/// [`pin module`]: crate::pin
+/// [`pin` module]: crate::pin
 #[stable(feature = "pin", since = "1.33.0")]
 #[rustc_on_unimplemented(
     on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
new file mode 100644
index 00000000000..687d423dcb6
--- /dev/null
+++ b/library/core/src/ops/control_flow.rs
@@ -0,0 +1,67 @@
+use crate::ops::Try;
+
+/// Used to make try_fold closures more like normal loops
+#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum ControlFlow<C, B> {
+    /// Continue in the loop, using the given value for the next iteration
+    Continue(C),
+    /// Exit the loop, yielding the given value
+    Break(B),
+}
+
+#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+impl<C, B> Try for ControlFlow<C, B> {
+    type Ok = C;
+    type Error = B;
+    #[inline]
+    fn into_result(self) -> Result<Self::Ok, Self::Error> {
+        match self {
+            ControlFlow::Continue(y) => Ok(y),
+            ControlFlow::Break(x) => Err(x),
+        }
+    }
+    #[inline]
+    fn from_error(v: Self::Error) -> Self {
+        ControlFlow::Break(v)
+    }
+    #[inline]
+    fn from_ok(v: Self::Ok) -> Self {
+        ControlFlow::Continue(v)
+    }
+}
+
+impl<C, B> ControlFlow<C, B> {
+    /// Converts the `ControlFlow` into an `Option` which is `Some` if the
+    /// `ControlFlow` was `Break` and `None` otherwise.
+    #[inline]
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    pub fn break_value(self) -> Option<B> {
+        match self {
+            ControlFlow::Continue(..) => None,
+            ControlFlow::Break(x) => Some(x),
+        }
+    }
+}
+
+impl<R: Try> ControlFlow<R::Ok, R> {
+    /// Create a `ControlFlow` from any type implementing `Try`.
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    #[inline]
+    pub fn from_try(r: R) -> Self {
+        match Try::into_result(r) {
+            Ok(v) => ControlFlow::Continue(v),
+            Err(v) => ControlFlow::Break(Try::from_error(v)),
+        }
+    }
+
+    /// Convert a `ControlFlow` into any type implementing `Try`;
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    #[inline]
+    pub fn into_try(self) -> R {
+        match self {
+            ControlFlow::Continue(v) => Try::from_ok(v),
+            ControlFlow::Break(v) => v,
+        }
+    }
+}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index c19bd6e441e..2a4186f9d5d 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -140,6 +140,7 @@
 
 mod arith;
 mod bit;
+mod control_flow;
 mod deref;
 mod drop;
 mod function;
@@ -191,3 +192,6 @@ pub use self::unsize::CoerceUnsized;
 
 #[unstable(feature = "dispatch_from_dyn", issue = "none")]
 pub use self::unsize::DispatchFromDyn;
+
+#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+pub use self::control_flow::ControlFlow;
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 81e621318e1..4a651e5aa0e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,5 +1,6 @@
 #![feature(alloc_layout_extra)]
 #![feature(array_chunks)]
+#![feature(array_methods)]
 #![feature(array_map)]
 #![feature(bool_to_option)]
 #![feature(bound_cloned)]
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index fa308160fc2..b46bcfd16d2 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -1,4 +1,3 @@
-use core::array::FixedSizeArray;
 use core::clone::Clone;
 use core::mem;
 use core::ops::DerefMut;
diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs
index caa2d916cd7..35598295a95 100644
--- a/library/core/tests/result.rs
+++ b/library/core/tests/result.rs
@@ -1,4 +1,3 @@
-use core::array::FixedSizeArray;
 use core::ops::DerefMut;
 use core::option::*;
 
diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs
index b3df6f49dc4..44d2937ee1b 100644
--- a/library/std/src/io/util.rs
+++ b/library/std/src/io/util.rs
@@ -52,11 +52,14 @@ where
     W: Write,
 {
     let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit();
-    // FIXME(#76092): This is calling `get_mut` and `get_ref` on an uninitialized
-    // `MaybeUninit`. Revisit this once we decided whether that is valid or not.
-    // This is still technically undefined behavior due to creating a reference
-    // to uninitialized data, but within libstd we can rely on more guarantees
-    // than if this code were in an external lib.
+    // FIXME: #42788
+    //
+    //   - This creates a (mut) reference to a slice of
+    //     _uninitialized_ integers, which is **undefined behavior**
+    //
+    //   - Only the standard library gets to soundly "ignore" this,
+    //     based on its privileged knowledge of unstable rustc
+    //     internals;
     unsafe {
         reader.initializer().initialize(buf.assume_init_mut());
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 3141b3b9526..dc57c1c1f44 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -240,6 +240,7 @@
 #![feature(const_fn_transmute)]
 #![feature(const_ipv6)]
 #![feature(const_raw_ptr_deref)]
+#![feature(const_ipv4)]
 #![feature(container_error_extra)]
 #![feature(core_intrinsics)]
 #![feature(custom_test_frameworks)]
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 341a112df71..3f9afae880f 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -365,8 +365,9 @@ impl Ipv4Addr {
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn octets(&self) -> [u8; 4] {
+    pub const fn octets(&self) -> [u8; 4] {
         // This returns the order we want because s_addr is stored in big-endian.
         self.inner.s_addr.to_ne_bytes()
     }
@@ -408,8 +409,9 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_loopback(&self) -> bool {
+    pub const fn is_loopback(&self) -> bool {
         self.octets()[0] == 127
     }
 
@@ -437,8 +439,9 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
     /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_private(&self) -> bool {
+    pub const fn is_private(&self) -> bool {
         match self.octets() {
             [10, ..] => true,
             [172, b, ..] if b >= 16 && b <= 31 => true,
@@ -463,8 +466,9 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
     /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_link_local(&self) -> bool {
+    pub const fn is_link_local(&self) -> bool {
         match self.octets() {
             [169, 254, ..] => true,
             _ => false,
@@ -542,10 +546,13 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
     /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
     /// ```
-    pub fn is_global(&self) -> bool {
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    pub const fn is_global(&self) -> bool {
         // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
         // globally routable addresses in the 192.0.0.0/24 range.
-        if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
+        if u32::from_be_bytes(self.octets()) == 0xc0000009
+            || u32::from_be_bytes(self.octets()) == 0xc000000a
+        {
             return true;
         }
         !self.is_private()
@@ -577,7 +584,8 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
     /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
     /// ```
-    pub fn is_shared(&self) -> bool {
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    pub const fn is_shared(&self) -> bool {
         self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
     }
 
@@ -609,7 +617,8 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
     /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
     /// ```
-    pub fn is_ietf_protocol_assignment(&self) -> bool {
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    pub const fn is_ietf_protocol_assignment(&self) -> bool {
         self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
     }
 
@@ -632,7 +641,8 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
     /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
     /// ```
-    pub fn is_benchmarking(&self) -> bool {
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    pub const fn is_benchmarking(&self) -> bool {
         self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
     }
 
@@ -664,7 +674,8 @@ impl Ipv4Addr {
     /// // The broadcast address is not considered as reserved for future use by this implementation
     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
     /// ```
-    pub fn is_reserved(&self) -> bool {
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    pub const fn is_reserved(&self) -> bool {
         self.octets()[0] & 240 == 240 && !self.is_broadcast()
     }
 
@@ -685,8 +696,9 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_multicast(&self) -> bool {
+    pub const fn is_multicast(&self) -> bool {
         self.octets()[0] >= 224 && self.octets()[0] <= 239
     }
 
@@ -705,9 +717,10 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_broadcast(&self) -> bool {
-        self == &Self::BROADCAST
+    pub const fn is_broadcast(&self) -> bool {
+        u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
     }
 
     /// Returns [`true`] if this address is in a range designated for documentation.
@@ -731,8 +744,9 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
     /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
-    pub fn is_documentation(&self) -> bool {
+    pub const fn is_documentation(&self) -> bool {
         match self.octets() {
             [192, 0, 2, _] => true,
             [198, 51, 100, _] => true,
@@ -745,6 +759,9 @@ impl Ipv4Addr {
     ///
     /// a.b.c.d becomes ::a.b.c.d
     ///
+    /// This isn't typically the method you want; these addresses don't typically
+    /// function on modern systems. Use `to_ipv6_mapped` instead.
+    ///
     /// [`IPv6` address]: Ipv6Addr
     ///
     /// # Examples
@@ -757,10 +774,13 @@ impl Ipv4Addr {
     ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
     /// );
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
+    pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
+        Ipv6Addr {
+            inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] },
+        }
     }
 
     /// Converts this address to an IPv4-mapped [`IPv6` address].
@@ -777,10 +797,13 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
     /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
+    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
         let [a, b, c, d] = self.octets();
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
+        Ipv6Addr {
+            inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] },
+        }
     }
 }
 
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index d00824cfb3e..2a4cb22cc52 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -510,7 +510,7 @@ mod prim_pointer {}
 /// an array. Indeed, this provides most of the API for working with arrays.
 /// Slices have a dynamic size and do not coerce to arrays.
 ///
-/// You can move elements out of an array with a slice pattern. If you want
+/// You can move elements out of an array with a [slice pattern]. If you want
 /// one element, see [`mem::replace`].
 ///
 /// # Examples
@@ -552,7 +552,7 @@ mod prim_pointer {}
 /// for x in &array { }
 /// ```
 ///
-/// You can use a slice pattern to move elements out of an array:
+/// You can use a [slice pattern] to move elements out of an array:
 ///
 /// ```
 /// fn move_away(_: String) { /* Do interesting things. */ }
@@ -567,7 +567,7 @@ mod prim_pointer {}
 /// [`Hash`]: hash::Hash
 /// [`Borrow`]: borrow::Borrow
 /// [`BorrowMut`]: borrow::BorrowMut
-///
+/// [slice pattern]: ../reference/patterns.html#slice-patterns
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_array {}
 
diff --git a/src/doc/book b/src/doc/book
-Subproject c0a6a61b8205da14ac955425f74258ffd8ee065
+Subproject e5ed97128302d5fa45dbac0e64426bc7649a558
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject bd6e4a9f59c5c1545f572266af77f5c7a5bad6d
+Subproject 81f16863014de60b53de401d71ff904d163ee03
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 1b6c4b0afab97c0230433466c97167bbbe8445f
+Subproject 25391dba46262f882fa846beefaff54a966a8fa
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 80a10e22140e28392b99d24ed02f4c6d8cb770a
+Subproject 19f0a0372af497b34369cf182d9d16156cab296
diff --git a/src/test/mir-opt/inline/inline-async.rs b/src/test/mir-opt/inline/inline-async.rs
new file mode 100644
index 00000000000..5c838159b98
--- /dev/null
+++ b/src/test/mir-opt/inline/inline-async.rs
@@ -0,0 +1,18 @@
+// Checks that inliner doesn't introduce cycles when optimizing generators.
+// The outcome of optimization is not verfied, just the absence of the cycle.
+// Regression test for #76181.
+//
+// edition:2018
+
+#![crate_type = "lib"]
+
+pub struct S;
+
+impl S {
+    pub async fn g(&mut self) {
+        self.h();
+    }
+    pub fn h(&mut self) {
+        let _ = self.g();
+    }
+}
diff --git a/src/test/ui/consts/std/net/ipv4.rs b/src/test/ui/consts/std/net/ipv4.rs
new file mode 100644
index 00000000000..8c676999ae7
--- /dev/null
+++ b/src/test/ui/consts/std/net/ipv4.rs
@@ -0,0 +1,58 @@
+// run-pass
+
+#![feature(ip)]
+#![feature(const_ipv4)]
+
+use std::net::{Ipv4Addr, Ipv6Addr};
+
+fn main() {
+    const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
+    assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
+
+    const OCTETS: [u8; 4] = IP_ADDRESS.octets();
+    assert_eq!(OCTETS, [127, 0, 0, 1]);
+
+    const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_PRIVATE : bool = IP_ADDRESS.is_private();
+    assert!(!IS_PRIVATE);
+
+    const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local();
+    assert!(!IS_LINK_LOCAL);
+
+    const IS_GLOBAL : bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_SHARED : bool = IP_ADDRESS.is_shared();
+    assert!(!IS_SHARED);
+
+    const IS_IETF_PROTOCOL_ASSIGNMENT : bool = IP_ADDRESS.is_ietf_protocol_assignment();
+    assert!(!IS_IETF_PROTOCOL_ASSIGNMENT);
+
+    const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking();
+    assert!(!IS_BENCHMARKING);
+
+    const IS_RESERVED : bool = IP_ADDRESS.is_reserved();
+    assert!(!IS_RESERVED);
+
+    const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IS_BROADCAST : bool = IP_ADDRESS.is_broadcast();
+    assert!(!IS_BROADCAST);
+
+    const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
+    assert!(!IS_DOCUMENTATION);
+
+    const IP_V6_COMPATIBLE : Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
+    assert_eq!(IP_V6_COMPATIBLE,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]));
+
+    const IP_V6_MAPPED : Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
+    assert_eq!(IP_V6_MAPPED,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]));
+}