about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock5
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/doc.rs59
-rw-r--r--src/bootstrap/flags.rs14
-rw-r--r--src/libcore/future/into_future.rs27
-rw-r--r--src/libcore/future/mod.rs4
-rw-r--r--src/libcore/mem/maybe_uninit.rs26
-rw-r--r--src/libproc_macro/lib.rs15
-rw-r--r--src/libproc_macro/tests/test.rs12
-rw-r--r--src/librustc_ast_lowering/lib.rs2
-rw-r--r--src/librustc_codegen_llvm/context.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs9
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs3
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs4
-rw-r--r--src/librustc_codegen_ssa/back/write.rs6
-rw-r--r--src/librustc_codegen_ssa/base.rs2
-rw-r--r--src/librustc_data_structures/Cargo.toml1
-rw-r--r--src/librustc_data_structures/sync.rs133
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_driver/pretty.rs4
-rw-r--r--src/librustc_error_codes/error_codes/E0599.md15
-rw-r--r--src/librustc_error_codes/error_codes/E0600.md2
-rw-r--r--src/librustc_interface/passes.rs21
-rw-r--r--src/librustc_interface/queries.rs6
-rw-r--r--src/librustc_interface/util.rs2
-rw-r--r--src/librustc_metadata/creader.rs4
-rw-r--r--src/librustc_metadata/dependency_format.rs3
-rw-r--r--src/librustc_metadata/locator.rs2
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs8
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs4
-rw-r--r--src/librustc_middle/arena.rs6
-rw-r--r--src/librustc_middle/middle/limits.rs8
-rw-r--r--src/librustc_middle/mir/predecessors.rs32
-rw-r--r--src/librustc_middle/ty/context.rs2
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_middle/ty/query/on_disk_cache.rs14
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs4
-rw-r--r--src/librustc_mir/interpret/eval_context.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs5
-rw-r--r--src/librustc_passes/entry.rs2
-rw-r--r--src/librustc_passes/reachable.rs2
-rw-r--r--src/librustc_passes/weak_lang_items.rs2
-rw-r--r--src/librustc_save_analysis/lib.rs5
-rw-r--r--src/librustc_session/parse.rs6
-rw-r--r--src/librustc_session/session.rs55
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs33
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs64
-rw-r--r--src/librustc_trait_selection/traits/project.rs6
-rw-r--r--src/librustc_trait_selection/traits/query/normalize.rs2
-rw-r--r--src/librustc_trait_selection/traits/select.rs3
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_ty/needs_drop.rs3
-rw-r--r--src/librustc_typeck/check/autoderef.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs72
-rw-r--r--src/librustdoc/html/static/rustdoc.css9
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs54
-rw-r--r--src/libstd/f32.rs2
-rw-r--r--src/libstd/f64.rs2
-rw-r--r--src/libstd/future.rs14
-rw-r--r--src/libstd/lib.rs3
-rw-r--r--src/test/incremental/issue-72386.rs22
-rw-r--r--src/test/rustdoc/intra-link-self.rs88
-rw-r--r--src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs3
-rw-r--r--src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr32
-rw-r--r--src/test/ui/issues/issue-72455.rs27
-rw-r--r--src/test/ui/suggestions/into-str.stderr1
-rw-r--r--src/test/ui/suggestions/issue-71394-no-from-impl.rs5
-rw-r--r--src/test/ui/suggestions/issue-71394-no-from-impl.stderr11
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rwxr-xr-xsrc/tools/publish_toolstate.py17
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--triagebot.toml6
74 files changed, 656 insertions, 381 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d81fd6e8d3a..6ce5458ed7a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -213,6 +213,7 @@ dependencies = [
  "lazy_static 1.4.0",
  "libc",
  "num_cpus",
+ "opener",
  "pretty_assertions",
  "serde",
  "serde_json",
@@ -2327,6 +2328,9 @@ name = "once_cell"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"
+dependencies = [
+ "parking_lot 0.9.0",
+]
 
 [[package]]
 name = "opaque-debug"
@@ -3791,6 +3795,7 @@ dependencies = [
  "libc",
  "log",
  "measureme",
+ "once_cell",
  "parking_lot 0.10.2",
  "rustc-hash",
  "rustc-rayon",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index f7856f6a7fc..c4918d7f2e7 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -48,6 +48,7 @@ toml = "0.5"
 lazy_static = "1.3.0"
 time = "0.1"
 ignore = "0.4.10"
+opener = "0.4"
 
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 4bc81a7b42d..5489b1bc66b 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -503,7 +503,7 @@ impl<'a> Builder<'a> {
             Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
             Subcommand::Clippy { ref paths } => (Kind::Clippy, &paths[..]),
             Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]),
-            Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
+            Subcommand::Doc { ref paths, .. } => (Kind::Doc, &paths[..]),
             Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
             Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
             Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 7eab92ddc92..5c01c5e852c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -70,6 +70,35 @@ book!(
     RustdocBook, "src/doc/rustdoc", "rustdoc";
 );
 
+fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
+    if builder.config.dry_run || !builder.config.cmd.open() {
+        return;
+    }
+
+    let path = path.as_ref();
+    builder.info(&format!("Opening doc {}", path.display()));
+    if let Err(err) = opener::open(path) {
+        builder.info(&format!("{}\n", err));
+    }
+}
+
+// "src/libstd" -> ["src", "libstd"]
+//
+// Used for deciding whether a particular step is one requested by the user on
+// the `x.py doc` command line, which determines whether `--open` will open that
+// page.
+fn components_simplified(path: &PathBuf) -> Vec<&str> {
+    path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
+}
+
+fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool {
+    builder
+        .paths
+        .iter()
+        .map(components_simplified)
+        .any(|requested| requested.iter().copied().eq(path.split("/")))
+}
+
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct UnstableBook {
     target: Interned<String>,
@@ -200,6 +229,12 @@ impl Step for TheBook {
 
             invoke_rustdoc(builder, compiler, target, path);
         }
+
+        if is_explicit_request(builder, "src/doc/book") {
+            let out = builder.doc_out(target);
+            let index = out.join("book").join("index.html");
+            open(builder, &index);
+        }
     }
 }
 
@@ -338,6 +373,13 @@ impl Step for Standalone {
             }
             builder.run(&mut cmd);
         }
+
+        // We open doc/index.html as the default if invoked as `x.py doc --open`
+        // with no particular explicit doc requested (e.g. src/libcore).
+        if builder.paths.is_empty() || is_explicit_request(builder, "src/doc") {
+            let index = out.join("index.html");
+            open(builder, &index);
+        }
     }
 }
 
@@ -418,10 +460,25 @@ impl Step for Std {
 
             builder.run(&mut cargo.into());
         };
-        for krate in &["alloc", "core", "std", "proc_macro", "test"] {
+        let krates = ["alloc", "core", "std", "proc_macro", "test"];
+        for krate in &krates {
             run_cargo_rustdoc_for(krate);
         }
         builder.cp_r(&my_out, &out);
+
+        // Look for src/libstd, src/libcore etc in the `x.py doc` arguments and
+        // open the corresponding rendered docs.
+        for path in builder.paths.iter().map(components_simplified) {
+            if path.get(0) == Some(&"src")
+                && path.get(1).map_or(false, |dir| dir.starts_with("lib"))
+            {
+                let requested_crate = &path[1][3..];
+                if krates.contains(&requested_crate) {
+                    let index = out.join(requested_crate).join("index.html");
+                    open(builder, &index);
+                }
+            }
+        }
     }
 }
 
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 646b9e05d99..cfaa43f3970 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -61,6 +61,7 @@ pub enum Subcommand {
     },
     Doc {
         paths: Vec<PathBuf>,
+        open: bool,
     },
     Test {
         paths: Vec<PathBuf>,
@@ -248,6 +249,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
             "bench" => {
                 opts.optmulti("", "test-args", "extra arguments", "ARGS");
             }
+            "doc" => {
+                opts.optflag("", "open", "open the docs in a browser");
+            }
             "clean" => {
                 opts.optflag("", "all", "clean all build artifacts");
             }
@@ -404,6 +408,7 @@ Arguments:
         ./x.py doc src/doc/book
         ./x.py doc src/doc/nomicon
         ./x.py doc src/doc/book src/libstd
+        ./x.py doc src/libstd --open
 
     If no arguments are passed then everything is documented:
 
@@ -479,7 +484,7 @@ Arguments:
                 },
             },
             "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
-            "doc" => Subcommand::Doc { paths },
+            "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
             "clean" => {
                 if !paths.is_empty() {
                     println!("\nclean does not take a path argument\n");
@@ -613,6 +618,13 @@ impl Subcommand {
             _ => None,
         }
     }
+
+    pub fn open(&self) -> bool {
+        match *self {
+            Subcommand::Doc { open, .. } => open,
+            _ => false,
+        }
+    }
 }
 
 fn split(s: &[String]) -> Vec<String> {
diff --git a/src/libcore/future/into_future.rs b/src/libcore/future/into_future.rs
new file mode 100644
index 00000000000..4020c254446
--- /dev/null
+++ b/src/libcore/future/into_future.rs
@@ -0,0 +1,27 @@
+use crate::future::Future;
+
+/// Conversion into a `Future`.
+#[unstable(feature = "into_future", issue = "67644")]
+pub trait IntoFuture {
+    /// The output that the future will produce on completion.
+    #[unstable(feature = "into_future", issue = "67644")]
+    type Output;
+
+    /// Which kind of future are we turning this into?
+    #[unstable(feature = "into_future", issue = "67644")]
+    type Future: Future<Output = Self::Output>;
+
+    /// Creates a future from a value.
+    #[unstable(feature = "into_future", issue = "67644")]
+    fn into_future(self) -> Self::Future;
+}
+
+#[unstable(feature = "into_future", issue = "67644")]
+impl<F: Future> IntoFuture for F {
+    type Output = F::Output;
+    type Future = F;
+
+    fn into_future(self) -> Self::Future {
+        self
+    }
+}
diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs
index b5a102916a0..6f6009b47e6 100644
--- a/src/libcore/future/mod.rs
+++ b/src/libcore/future/mod.rs
@@ -10,12 +10,16 @@ use crate::{
 };
 
 mod future;
+mod into_future;
 mod pending;
 mod ready;
 
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub use self::future::Future;
 
+#[unstable(feature = "into_future", issue = "67644")]
+pub use into_future::IntoFuture;
+
 #[unstable(feature = "future_readiness_fns", issue = "70921")]
 pub use pending::{pending, Pending};
 #[unstable(feature = "future_readiness_fns", issue = "70921")]
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index f7ea7eba7b1..01c97444ae3 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -20,9 +20,9 @@ use crate::mem::ManuallyDrop;
 /// # #![allow(invalid_value)]
 /// use std::mem::{self, MaybeUninit};
 ///
-/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
+/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️
 /// // The equivalent code with `MaybeUninit<&i32>`:
-/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
+/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️
 /// ```
 ///
 /// This is exploited by the compiler for various optimizations, such as eliding
@@ -35,9 +35,9 @@ use crate::mem::ManuallyDrop;
 /// # #![allow(invalid_value)]
 /// use std::mem::{self, MaybeUninit};
 ///
-/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
+/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
 /// // The equivalent code with `MaybeUninit<bool>`:
-/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
 /// ```
 ///
 /// Moreover, uninitialized memory is special in that the compiler knows that
@@ -49,9 +49,9 @@ use crate::mem::ManuallyDrop;
 /// # #![allow(invalid_value)]
 /// use std::mem::{self, MaybeUninit};
 ///
-/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
+/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
 /// // The equivalent code with `MaybeUninit<i32>`:
-/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
 /// ```
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
@@ -348,7 +348,7 @@ impl<T> MaybeUninit<T> {
     /// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
     /// let x = unsafe { x.assume_init() };
     /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
-    /// // This is undefined behavior.
+    /// // This is undefined behavior. ⚠️
     /// ```
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline]
@@ -400,7 +400,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
     /// let x_vec = unsafe { &*x.as_ptr() };
-    /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+    /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
     /// ```
     ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
@@ -437,7 +437,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
     /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
-    /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+    /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
     /// ```
     ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
@@ -489,7 +489,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
     /// let x_init = unsafe { x.assume_init() };
-    /// // `x` had not been initialized yet, so this last line caused undefined behavior.
+    /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
     /// ```
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
@@ -553,7 +553,7 @@ impl<T> MaybeUninit<T> {
     /// x.write(Some(vec![0,1,2]));
     /// let x1 = unsafe { x.read() };
     /// let x2 = unsafe { x.read() };
-    /// // We now created two copies of the same vector, leading to a double-free when
+    /// // We now created two copies of the same vector, leading to a double-free ⚠️ when
     /// // they both get dropped!
     /// ```
     #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
@@ -603,7 +603,7 @@ impl<T> MaybeUninit<T> {
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
     /// let x_vec: &Vec<u32> = unsafe { x.get_ref() };
-    /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+    /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
     /// ```
     ///
     /// ```rust,no_run
@@ -686,7 +686,7 @@ impl<T> MaybeUninit<T> {
     /// unsafe {
     ///     *b.get_mut() = true;
     ///     // We have created a (mutable) reference to an uninitialized `bool`!
-    ///     // This is undefined behavior.
+    ///     // This is undefined behavior. ⚠️
     /// }
     /// ```
     ///
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index f11401b5a0c..2d5bd7e872b 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -39,6 +39,7 @@ mod diagnostic;
 #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
 
+use std::cmp::Ordering;
 use std::ops::{Bound, RangeBounds};
 use std::path::PathBuf;
 use std::str::FromStr;
@@ -420,6 +421,20 @@ impl !Send for LineColumn {}
 #[unstable(feature = "proc_macro_span", issue = "54725")]
 impl !Sync for LineColumn {}
 
+#[unstable(feature = "proc_macro_span", issue = "54725")]
+impl Ord for LineColumn {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.line.cmp(&other.line).then(self.column.cmp(&other.column))
+    }
+}
+
+#[unstable(feature = "proc_macro_span", issue = "54725")]
+impl PartialOrd for LineColumn {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
 /// The source file of a given `Span`.
 #[unstable(feature = "proc_macro_span", issue = "54725")]
 #[derive(Clone)]
diff --git a/src/libproc_macro/tests/test.rs b/src/libproc_macro/tests/test.rs
new file mode 100644
index 00000000000..331b330cf29
--- /dev/null
+++ b/src/libproc_macro/tests/test.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_span)]
+
+use proc_macro::LineColumn;
+
+#[test]
+fn test_line_column_ord() {
+    let line0_column0 = LineColumn { line: 0, column: 0 };
+    let line0_column1 = LineColumn { line: 0, column: 1 };
+    let line1_column0 = LineColumn { line: 1, column: 0 };
+    assert!(line0_column0 < line0_column1);
+    assert!(line0_column1 < line1_column0);
+}
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 2cf81af0416..0eabb726b88 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -269,7 +269,7 @@ pub fn lower_crate<'a, 'hir>(
     let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering");
 
     LoweringContext {
-        crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
+        crate_root: sess.parse_sess.injected_crate_name.get().copied(),
         sess,
         resolver,
         nt_to_tokenstream,
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 3192d4fc157..4c810a37d41 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -174,7 +174,7 @@ pub unsafe fn create_module(
         llvm::LLVMRustSetModulePICLevel(llmod);
         // PIE is potentially more effective than PIC, but can only be used in executables.
         // If all our outputs are executables, then we can relax PIC to PIE.
-        if sess.crate_types.get().iter().all(|ty| *ty == CrateType::Executable) {
+        if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
             llvm::LLVMRustSetModulePIELevel(llmod);
         }
     }
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 5de60b5b9c8..9a7c4907754 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -53,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
 ) {
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
-    for &crate_type in sess.crate_types.borrow().iter() {
+    for &crate_type in sess.crate_types().iter() {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
         if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen())
             && !output_metadata
@@ -875,11 +875,8 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
 
     // If we're only producing artifacts that are archives, no need to preserve
     // the objects as they're losslessly contained inside the archives.
-    let output_linked = sess
-        .crate_types
-        .borrow()
-        .iter()
-        .any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib);
+    let output_linked =
+        sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib);
     if !output_linked {
         return false;
     }
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index ee5bcf4b9f5..49de8c5e28a 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -44,8 +44,7 @@ impl LinkerInfo {
         LinkerInfo {
             exports: tcx
                 .sess
-                .crate_types
-                .borrow()
+                .crate_types()
                 .iter()
                 .map(|&c| (c, exported_symbols(tcx, c)))
                 .collect(),
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index c0272e1cd2d..970d13b30c0 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::{SymbolName, TyCtxt};
 use rustc_session::config::{CrateType, Sanitizer};
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
-    crates_export_threshold(&tcx.sess.crate_types.borrow())
+    crates_export_threshold(&tcx.sess.crate_types())
 }
 
 fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
@@ -212,7 +212,7 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if tcx.sess.crate_types.borrow().contains(&CrateType::Dylib) {
+    if tcx.sess.crate_types().contains(&CrateType::Dylib) {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
 
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index f9ee7d8c5de..9e03c283cfb 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -382,7 +382,7 @@ pub struct CompiledModules {
 
 fn need_bitcode_in_object(sess: &Session) -> bool {
     let requested_for_rlib = sess.opts.cg.embed_bitcode
-        && sess.crate_types.borrow().contains(&CrateType::Rlib)
+        && sess.crate_types().contains(&CrateType::Rlib)
         && sess.opts.output_types.contains_key(&OutputType::Exe);
     let forced_by_target = sess.target.target.options.forces_embed_bitcode;
     requested_for_rlib || forced_by_target
@@ -991,7 +991,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     };
     let cgcx = CodegenContext::<B> {
         backend: backend.clone(),
-        crate_types: sess.crate_types.borrow().clone(),
+        crate_types: sess.crate_types().to_vec(),
         each_linked_rlib_for_lto,
         lto: sess.lto(),
         no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort,
@@ -1812,7 +1812,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     );
 
     tcx.sess.target.target.options.is_like_msvc &&
-        tcx.sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Rlib) &&
+        tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
     // ThinLTO can't handle this workaround in all cases, so we don't
     // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
     // dynamic linking when linker plugin LTO is enabled.
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index ed5448ca8ba..5b14258bd25 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -948,7 +948,7 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
         match compute_per_cgu_lto_type(
             &tcx.sess.lto(),
             &tcx.sess.opts,
-            &tcx.sess.crate_types.borrow(),
+            &tcx.sess.crate_types(),
             ModuleKind::Regular,
         ) {
             ComputedLtoType::No => CguReuse::PostLto,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 81ad032967b..67721220526 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -15,6 +15,7 @@ indexmap = "1"
 log = "0.4"
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
+once_cell = { version = "1", features = ["parking_lot"] }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 graphviz = { path = "../libgraphviz" }
 cfg-if = "0.1.2"
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 9051b1751b1..39afb3d82ff 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -20,7 +20,6 @@
 use crate::owning_ref::{Erased, OwningRef};
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
-use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut};
 
 pub use std::sync::atomic::Ordering;
@@ -230,6 +229,8 @@ cfg_if! {
         pub use std::cell::RefMut as LockGuard;
         pub use std::cell::RefMut as MappedLockGuard;
 
+        pub use once_cell::unsync::OnceCell;
+
         use std::cell::RefCell as InnerRwLock;
         use std::cell::RefCell as InnerLock;
 
@@ -313,6 +314,8 @@ cfg_if! {
         pub use parking_lot::MutexGuard as LockGuard;
         pub use parking_lot::MappedMutexGuard as MappedLockGuard;
 
+        pub use once_cell::sync::OnceCell;
+
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
         pub use crossbeam_utils::atomic::AtomicCell;
@@ -432,134 +435,6 @@ impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
     }
 }
 
-/// A type whose inner value can be written once and then will stay read-only
-// This contains a PhantomData<T> since this type conceptually owns a T outside the Mutex once
-// initialized. This ensures that Once<T> is Sync only if T is. If we did not have PhantomData<T>
-// we could send a &Once<Cell<bool>> to multiple threads and call `get` on it to get access
-// to &Cell<bool> on those threads.
-pub struct Once<T>(Lock<Option<T>>, PhantomData<T>);
-
-impl<T> Once<T> {
-    /// Creates an Once value which is uninitialized
-    #[inline(always)]
-    pub fn new() -> Self {
-        Once(Lock::new(None), PhantomData)
-    }
-
-    /// Consumes the value and returns Some(T) if it was initialized
-    #[inline(always)]
-    pub fn into_inner(self) -> Option<T> {
-        self.0.into_inner()
-    }
-
-    /// Tries to initialize the inner value to `value`.
-    /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
-    /// otherwise if the inner value was already set it returns `value` back to the caller
-    #[inline]
-    pub fn try_set(&self, value: T) -> Option<T> {
-        let mut lock = self.0.lock();
-        if lock.is_some() {
-            return Some(value);
-        }
-        *lock = Some(value);
-        None
-    }
-
-    /// Tries to initialize the inner value to `value`.
-    /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
-    /// otherwise if the inner value was already set it asserts that `value` is equal to the inner
-    /// value and then returns `value` back to the caller
-    #[inline]
-    pub fn try_set_same(&self, value: T) -> Option<T>
-    where
-        T: Eq,
-    {
-        let mut lock = self.0.lock();
-        if let Some(ref inner) = *lock {
-            assert!(*inner == value);
-            return Some(value);
-        }
-        *lock = Some(value);
-        None
-    }
-
-    /// Tries to initialize the inner value to `value` and panics if it was already initialized
-    #[inline]
-    pub fn set(&self, value: T) {
-        assert!(self.try_set(value).is_none());
-    }
-
-    /// Initializes the inner value if it wasn't already done by calling the provided closure. It
-    /// ensures that no-one else can access the value in the mean time by holding a lock for the
-    /// duration of the closure.
-    /// A reference to the inner value is returned.
-    #[inline]
-    pub fn init_locking<F: FnOnce() -> T>(&self, f: F) -> &T {
-        {
-            let mut lock = self.0.lock();
-            if lock.is_none() {
-                *lock = Some(f());
-            }
-        }
-
-        self.borrow()
-    }
-
-    /// Tries to initialize the inner value by calling the closure without ensuring that no-one
-    /// else can access it. This mean when this is called from multiple threads, multiple
-    /// closures may concurrently be computing a value which the inner value should take.
-    /// Only one of these closures are used to actually initialize the value.
-    /// If some other closure already set the value,
-    /// we return the value our closure computed wrapped in a `Option`.
-    /// If our closure set the value, `None` is returned.
-    /// If the value is already initialized, the closure is not called and `None` is returned.
-    #[inline]
-    pub fn init_nonlocking<F: FnOnce() -> T>(&self, f: F) -> Option<T> {
-        if self.0.lock().is_some() { None } else { self.try_set(f()) }
-    }
-
-    /// Tries to initialize the inner value by calling the closure without ensuring that no-one
-    /// else can access it. This mean when this is called from multiple threads, multiple
-    /// closures may concurrently be computing a value which the inner value should take.
-    /// Only one of these closures are used to actually initialize the value.
-    /// If some other closure already set the value, we assert that it our closure computed
-    /// a value equal to the value already set and then
-    /// we return the value our closure computed wrapped in a `Option`.
-    /// If our closure set the value, `None` is returned.
-    /// If the value is already initialized, the closure is not called and `None` is returned.
-    #[inline]
-    pub fn init_nonlocking_same<F: FnOnce() -> T>(&self, f: F) -> Option<T>
-    where
-        T: Eq,
-    {
-        if self.0.lock().is_some() { None } else { self.try_set_same(f()) }
-    }
-
-    /// Tries to get a reference to the inner value, returns `None` if it is not yet initialized
-    #[inline(always)]
-    pub fn try_get(&self) -> Option<&T> {
-        let lock = &*self.0.lock();
-        if let Some(ref inner) = *lock {
-            // This is safe since we won't mutate the inner value
-            unsafe { Some(&*(inner as *const T)) }
-        } else {
-            None
-        }
-    }
-
-    /// Gets reference to the inner value, panics if it is not yet initialized
-    #[inline(always)]
-    pub fn get(&self) -> &T {
-        self.try_get().expect("value was not set")
-    }
-
-    /// Gets reference to the inner value, panics if it is not yet initialized
-    #[inline(always)]
-    pub fn borrow(&self) -> &T {
-        self.get()
-    }
-}
-
 #[derive(Debug)]
 pub struct Lock<T>(InnerLock<T>);
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 6847b175e60..68ce93d3db9 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -586,7 +586,7 @@ impl RustcDefaultCalls {
         if let Input::File(file) = compiler.input() {
             // FIXME: #![crate_type] and #![crate_name] support not implemented yet
             let attrs = vec![];
-            sess.crate_types.set(collect_crate_types(sess, &attrs));
+            sess.init_crate_types(collect_crate_types(sess, &attrs));
             let outputs = compiler.build_output_filenames(&sess, &attrs);
             let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| {
                 sess.fatal(&format!("failed to read rlink file: {}", err));
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index a443b8f464f..0a21eb8de05 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -396,7 +396,7 @@ pub fn print_after_parsing(
                 annotation.pp_ann(),
                 false,
                 parse.edition,
-                parse.injected_crate_name.try_get().is_some(),
+                parse.injected_crate_name.get().is_some(),
             )
         })
     } else {
@@ -438,7 +438,7 @@ pub fn print_after_hir_lowering<'tcx>(
                     annotation.pp_ann(),
                     true,
                     parse.edition,
-                    parse.injected_crate_name.try_get().is_some(),
+                    parse.injected_crate_name.get().is_some(),
                 )
             })
         }
diff --git a/src/librustc_error_codes/error_codes/E0599.md b/src/librustc_error_codes/error_codes/E0599.md
index c44e60571e1..5b1590b2999 100644
--- a/src/librustc_error_codes/error_codes/E0599.md
+++ b/src/librustc_error_codes/error_codes/E0599.md
@@ -9,3 +9,18 @@ let x = Mouth;
 x.chocolate(); // error: no method named `chocolate` found for type `Mouth`
                //        in the current scope
 ```
+
+In this case, you need to implement the `chocolate` method to fix the error:
+
+```
+struct Mouth;
+
+impl Mouth {
+    fn chocolate(&self) { // We implement the `chocolate` method here.
+        println!("Hmmm! I love chocolate!");
+    }
+}
+
+let x = Mouth;
+x.chocolate(); // ok!
+```
diff --git a/src/librustc_error_codes/error_codes/E0600.md b/src/librustc_error_codes/error_codes/E0600.md
index 172e2a346c5..356006c72f3 100644
--- a/src/librustc_error_codes/error_codes/E0600.md
+++ b/src/librustc_error_codes/error_codes/E0600.md
@@ -1,6 +1,6 @@
 An unary operator was used on a type which doesn't implement it.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0600
 enum Question {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 801c8e9329b..214701db724 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -7,7 +7,7 @@ use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self, ast, visit};
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::sync::{par_iter, Lrc, Once, ParallelIterator, WorkerLocal};
+use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
@@ -169,10 +169,10 @@ pub fn register_plugins<'a>(
     sess.init_features(features);
 
     let crate_types = util::collect_crate_types(sess, &krate.attrs);
-    sess.crate_types.set(crate_types);
+    sess.init_crate_types(crate_types);
 
     let disambiguator = util::compute_crate_disambiguator(sess);
-    sess.crate_disambiguator.set(disambiguator);
+    sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
     rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
 
     if sess.opts.incremental.is_some() {
@@ -244,7 +244,7 @@ fn configure_and_expand_inner<'a>(
             alt_std_name,
         );
         if let Some(name) = name {
-            sess.parse_sess.injected_crate_name.set(name);
+            sess.parse_sess.injected_crate_name.set(name).expect("not yet initialized");
         }
         krate
     });
@@ -288,7 +288,7 @@ fn configure_and_expand_inner<'a>(
         let features = sess.features_untracked();
         let cfg = rustc_expand::expand::ExpansionConfig {
             features: Some(&features),
-            recursion_limit: *sess.recursion_limit.get(),
+            recursion_limit: sess.recursion_limit(),
             trace_mac: sess.opts.debugging_opts.trace_macros,
             should_test: sess.opts.test,
             ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
@@ -358,7 +358,7 @@ fn configure_and_expand_inner<'a>(
         rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
     });
 
-    let crate_types = sess.crate_types.borrow();
+    let crate_types = sess.crate_types();
     let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
 
     // For backwards compatibility, we don't try to run proc macro injection
@@ -488,7 +488,7 @@ fn generated_output_paths(
             // If the filename has been overridden using `-o`, it will not be modified
             // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
             OutputType::Exe if !exact_name => {
-                for crate_type in sess.crate_types.borrow().iter() {
+                for crate_type in sess.crate_types().iter() {
                     let p = filename_for_input(sess, *crate_type, crate_name, outputs);
                     out_filenames.push(p);
                 }
@@ -721,7 +721,7 @@ pub fn create_global_ctxt<'tcx>(
     mut resolver_outputs: ResolverOutputs,
     outputs: OutputFilenames,
     crate_name: &str,
-    global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
+    global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
@@ -743,7 +743,7 @@ pub fn create_global_ctxt<'tcx>(
     }
 
     let gcx = sess.time("setup_global_ctxt", || {
-        global_ctxt.init_locking(|| {
+        global_ctxt.get_or_init(|| {
             TyCtxt::create_global_ctxt(
                 sess,
                 lint_store,
@@ -905,8 +905,7 @@ fn encode_and_write_metadata(
 
     let metadata_kind = tcx
         .sess
-        .crate_types
-        .borrow()
+        .crate_types()
         .iter()
         .map(|ty| match *ty {
             CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => MetadataKind::None,
diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs
index 94cd4bcd4c6..283be165c19 100644
--- a/src/librustc_interface/queries.rs
+++ b/src/librustc_interface/queries.rs
@@ -3,7 +3,7 @@ use crate::passes::{self, BoxedResolver, QueryContext};
 
 use rustc_ast::{self, ast};
 use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::Crate;
@@ -65,7 +65,7 @@ impl<T> Default for Query<T> {
 
 pub struct Queries<'tcx> {
     compiler: &'tcx Compiler,
-    gcx: Once<GlobalCtxt<'tcx>>,
+    gcx: OnceCell<GlobalCtxt<'tcx>>,
 
     arena: WorkerLocal<Arena<'tcx>>,
     hir_arena: WorkerLocal<rustc_ast_lowering::Arena<'tcx>>,
@@ -86,7 +86,7 @@ impl<'tcx> Queries<'tcx> {
     pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
         Queries {
             compiler,
-            gcx: Once::new(),
+            gcx: OnceCell::new(),
             arena: WorkerLocal::new(|_| Arena::default()),
             hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()),
             dep_graph_future: Default::default(),
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 5a76802014e..a15da94a215 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -406,7 +406,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat
 
     // Also incorporate crate type, so that we don't get symbol conflicts when
     // linking against a library of the same name, if this is an executable.
-    let is_exe = session.crate_types.borrow().contains(&CrateType::Executable);
+    let is_exe = session.crate_types().contains(&CrateType::Executable);
     hasher.write(if is_exe { b"exe" } else { b"lib" });
 
     CrateDisambiguator::from(hasher.finish::<Fingerprint>())
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index a9e7a9f35dc..b0220ddd3c3 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -615,7 +615,7 @@ impl<'a> CrateLoader<'a> {
     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
-        let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| *ct != CrateType::Rlib);
+        let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
         if !any_non_rlib {
             info!("panic runtime injection skipped, only generating rlib");
             return;
@@ -734,7 +734,7 @@ impl<'a> CrateLoader<'a> {
         // At this point we've determined that we need an allocator. Let's see
         // if our compilation session actually needs an allocator based on what
         // we're emitting.
-        let all_rlib = self.sess.crate_types.borrow().iter().all(|ct| match *ct {
+        let all_rlib = self.sess.crate_types().iter().all(|ct| match *ct {
             CrateType::Rlib => true,
             _ => false,
         });
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 0876cd1e638..aa5fafcc614 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -64,8 +64,7 @@ use rustc_target::spec::PanicStrategy;
 
 crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
     tcx.sess
-        .crate_types
-        .borrow()
+        .crate_types()
         .iter()
         .map(|&ty| {
             let linkage = calculate_type(tcx, ty);
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index f78f3c5d8d4..5a4862d4521 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -670,7 +670,7 @@ impl<'a> CrateLocator<'a> {
 
         // The all loop is because `--crate-type=rlib --crate-type=rlib` is
         // legal and produces both inside this type.
-        let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == CrateType::Rlib);
+        let is_rlib = self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
         let needs_object_code = self.sess.opts.output_types.should_codegen();
         // If we're producing an rlib, then we don't need object code.
         // Or, if we're not producing object code, then we don't need it either
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 220d7496075..2b292b35c15 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once};
+use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
 use rustc_hir as hir;
@@ -79,7 +79,7 @@ crate struct CrateMetadata {
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
-    source_map_import_info: Once<Vec<ImportedSourceFile>>,
+    source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     alloc_decoding_state: AllocDecodingState,
     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
@@ -1486,7 +1486,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             }
         };
 
-        self.cdata.source_map_import_info.init_locking(|| {
+        self.cdata.source_map_import_info.get_or_init(|| {
             let external_source_map = self.root.source_map.decode(self);
 
             external_source_map
@@ -1600,7 +1600,7 @@ impl CrateMetadata {
             def_path_table,
             trait_impls,
             raw_proc_macros,
-            source_map_import_info: Once::new(),
+            source_map_import_info: OnceCell::new(),
             alloc_decoding_state,
             dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
             cnum,
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index ebe91d3cee2..91fbfcc0133 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -416,7 +416,7 @@ impl<'tcx> EncodeContext<'tcx> {
     }
 
     fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
-        let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
+        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
 
         let mut i = self.position();
 
@@ -1364,7 +1364,7 @@ impl EncodeContext<'tcx> {
     }
 
     fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
-        let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
+        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
             Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)))
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index a97db3134dc..2df878c3fb2 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -76,6 +76,12 @@ macro_rules! arena_types {
             [few] hir_definitions: rustc_hir::definitions::Definitions,
             [] hir_owner: rustc_middle::hir::Owner<$tcx>,
             [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
+
+            // Note that this deliberately duplicates items in the `rustc_hir::arena`,
+            // since we need to allocate this type on both the `rustc_hir` arena
+            // (during lowering) and the `librustc_middle` arena (for decoding MIR)
+            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+
         ], $tcx);
     )
 }
diff --git a/src/librustc_middle/middle/limits.rs b/src/librustc_middle/middle/limits.rs
index c43c22cd61b..19c056925cf 100644
--- a/src/librustc_middle/middle/limits.rs
+++ b/src/librustc_middle/middle/limits.rs
@@ -7,7 +7,7 @@
 
 use crate::bug;
 use rustc_ast::ast;
-use rustc_data_structures::sync::Once;
+use rustc_data_structures::sync::OnceCell;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 
@@ -22,7 +22,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) {
 fn update_limit(
     sess: &Session,
     krate: &ast::Crate,
-    limit: &Once<usize>,
+    limit: &OnceCell<usize>,
     name: Symbol,
     default: usize,
 ) {
@@ -34,7 +34,7 @@ fn update_limit(
         if let Some(s) = attr.value_str() {
             match s.as_str().parse() {
                 Ok(n) => {
-                    limit.set(n);
+                    limit.set(n).unwrap();
                     return;
                 }
                 Err(e) => {
@@ -62,5 +62,5 @@ fn update_limit(
             }
         }
     }
-    limit.set(default);
+    limit.set(default).unwrap();
 }
diff --git a/src/librustc_middle/mir/predecessors.rs b/src/librustc_middle/mir/predecessors.rs
index 9508365886a..7508c023939 100644
--- a/src/librustc_middle/mir/predecessors.rs
+++ b/src/librustc_middle/mir/predecessors.rs
@@ -1,7 +1,7 @@
 //! Lazily compute the reverse control-flow graph for the MIR.
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::sync::OnceCell;
 use rustc_index::vec::IndexVec;
 use rustc_serialize as serialize;
 use smallvec::SmallVec;
@@ -13,37 +13,33 @@ pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
 
 #[derive(Clone, Debug)]
 pub(super) struct PredecessorCache {
-    cache: Lock<Option<Lrc<Predecessors>>>,
+    cache: OnceCell<Predecessors>,
 }
 
 impl PredecessorCache {
     #[inline]
     pub(super) fn new() -> Self {
-        PredecessorCache { cache: Lock::new(None) }
+        PredecessorCache { cache: OnceCell::new() }
     }
 
     /// Invalidates the predecessor cache.
-    ///
-    /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
-    /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
-    /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
-    /// cache. This means we don't actually need to take a lock when `invalidate` is called.
     #[inline]
     pub(super) fn invalidate(&mut self) {
-        *self.cache.get_mut() = None;
+        // Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
+        // unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
+        // callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
+        // cache. This means we never need to do synchronization when `invalidate` is called, we can
+        // simply reinitialize the `OnceCell`.
+        self.cache = OnceCell::new();
     }
 
-    /// Returns a ref-counted smart pointer containing the predecessor graph for this MIR.
-    ///
-    /// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for
-    /// `cache` is only held inside this function. As long as no other locks are taken while
-    /// computing the predecessor graph, deadlock is impossible.
+    /// Returns the the predecessor graph for this MIR.
     #[inline]
     pub(super) fn compute(
         &self,
         basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
-    ) -> Lrc<Predecessors> {
-        Lrc::clone(self.cache.lock().get_or_insert_with(|| {
+    ) -> &Predecessors {
+        self.cache.get_or_init(|| {
             let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
             for (bb, data) in basic_blocks.iter_enumerated() {
                 if let Some(term) = &data.terminator {
@@ -53,8 +49,8 @@ impl PredecessorCache {
                 }
             }
 
-            Lrc::new(preds)
-        }))
+            preds
+        })
     }
 }
 
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 5d48b3445e8..68c31c68075 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1380,7 +1380,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn local_crate_exports_generics(self) -> bool {
         debug_assert!(self.sess.opts.share_generics());
 
-        self.sess.crate_types.borrow().iter().any(|crate_type| {
+        self.sess.crate_types().iter().any(|crate_type| {
             match crate_type {
                 CrateType::Executable
                 | CrateType::Staticlib
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 2d49d85c4df..5566e187c0c 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -187,7 +187,7 @@ fn layout_raw<'tcx>(
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Result<&'tcx Layout, LayoutError<'tcx>> {
     ty::tls::with_related_context(tcx, move |icx| {
-        let rec_limit = *tcx.sess.recursion_limit.get();
+        let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap();
         let (param_env, ty) = query.into_parts();
 
         if icx.layout_depth > rec_limit {
diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs
index 71c2c24cc0a..4eae06742d9 100644
--- a/src/librustc_middle/ty/query/on_disk_cache.rs
+++ b/src/librustc_middle/ty/query/on_disk_cache.rs
@@ -6,7 +6,7 @@ use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once};
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
@@ -49,7 +49,7 @@ pub struct OnDiskCache<'sess> {
     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
 
     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
-    cnum_map: Once<IndexVec<CrateNum, Option<CrateNum>>>,
+    cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
 
     source_map: &'sess SourceMap,
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
@@ -128,7 +128,7 @@ impl<'sess> OnDiskCache<'sess> {
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
             prev_cnums: footer.prev_cnums,
-            cnum_map: Once::new(),
+            cnum_map: OnceCell::new(),
             source_map: sess.source_map(),
             current_diagnostics: Default::default(),
             query_result_index: footer.query_result_index.into_iter().collect(),
@@ -144,7 +144,7 @@ impl<'sess> OnDiskCache<'sess> {
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
             prev_cnums: vec![],
-            cnum_map: Once::new(),
+            cnum_map: OnceCell::new(),
             source_map,
             current_diagnostics: Default::default(),
             query_result_index: Default::default(),
@@ -370,14 +370,14 @@ impl<'sess> OnDiskCache<'sess> {
     {
         let pos = index.get(&dep_node_index).cloned()?;
 
-        // Initialize `cnum_map` using the value from the thread that finishes the closure first.
-        self.cnum_map.init_nonlocking_same(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
+        let cnum_map =
+            self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
 
         let mut decoder = CacheDecoder {
             tcx,
             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
             source_map: self.source_map,
-            cnum_map: self.cnum_map.get(),
+            cnum_map,
             synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 0637ebf959e..fd5e0632a2c 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -89,7 +89,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
     InterpCx::new(
         tcx.at(span),
         param_env,
-        CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
+        CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics },
     )
 }
@@ -303,7 +303,7 @@ pub fn const_eval_raw_provider<'tcx>(
     let mut ecx = InterpCx::new(
         tcx.at(span),
         key.param_env,
-        CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()),
+        CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics: is_static },
     );
 
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index eba4dd336ad..4f91257e2ef 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -651,7 +651,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         M::after_stack_push(self)?;
         info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
 
-        if self.stack().len() > *self.tcx.sess.recursion_limit.get() {
+        if self.stack().len() > self.tcx.sess.recursion_limit() {
             throw_exhaust!(StackFrameLimitReached)
         } else {
             Ok(())
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 925b8d32966..081f6435d9d 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -430,7 +430,7 @@ fn check_recursion_limit<'tcx>(
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() {
+    if adjusted_recursion_depth > tcx.sess.recursion_limit() {
         let error = format!("reached the recursion limit while instantiating `{}`", instance);
         if let Some(def_id) = def_id.as_local() {
             let hir_id = tcx.hir().as_local_hir_id(def_id);
@@ -463,8 +463,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     // which means that rustc basically hangs.
     //
     // Bail out in these cases to avoid that bad user experience.
-    let type_length_limit = *tcx.sess.type_length_limit.get();
-    if type_length > type_length_limit {
+    if type_length > tcx.sess.type_length_limit() {
         // The instance name is already known to be too long for rustc.
         // Show only the first and last 32 characters to avoid blasting
         // the user's terminal with thousands of lines of type-name.
diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs
index d2f1d11256b..e0ad0ac7747 100644
--- a/src/librustc_passes/entry.rs
+++ b/src/librustc_passes/entry.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
 fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> {
     assert_eq!(cnum, LOCAL_CRATE);
 
-    let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| *ty == CrateType::Executable);
+    let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
     if !any_exe {
         // No need to find a main function.
         return None;
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 7c169d68132..cac71b3836c 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -376,7 +376,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
     let any_library =
-        tcx.sess.crate_types.borrow().iter().any(|ty| {
+        tcx.sess.crate_types().iter().any(|ty| {
             *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro
         });
     let mut reachable_context = ReachableContext {
diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs
index 8a581626862..96ec23692df 100644
--- a/src/librustc_passes/weak_lang_items.rs
+++ b/src/librustc_passes/weak_lang_items.rs
@@ -37,7 +37,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
 fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
     // emitting something that's not an rlib.
-    let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| match *kind {
+    let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
         CrateType::Dylib
         | CrateType::ProcMacro
         | CrateType::Cdylib
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 43fd2b18530..3bd68a9c656 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -87,7 +87,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
     pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
         let sess = &self.tcx.sess;
         // Save-analysis is emitted per whole session, not per each crate type
-        let crate_type = sess.crate_types.borrow()[0];
+        let crate_type = sess.crate_types()[0];
         let outputs = &*self.tcx.output_filenames(LOCAL_CRATE);
 
         if outputs.outputs.contains_key(&OutputType::Metadata) {
@@ -987,8 +987,7 @@ impl<'a> DumpHandler<'a> {
                     error!("Could not create directory {}: {}", root_path.display(), e);
                 }
 
-                let executable =
-                    sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Executable);
+                let executable = sess.crate_types().iter().any(|ct| *ct == CrateType::Executable);
                 let mut out_name = if executable { String::new() } else { "lib".to_owned() };
                 out_name.push_str(&self.cratename);
                 out_name.push_str(&sess.opts.cg.extra_filename);
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 69d3e99b745..746e3536ce9 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -4,7 +4,7 @@
 use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
 use rustc_ast::node_id::NodeId;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::{Lock, Lrc, Once};
+use rustc_data_structures::sync::{Lock, Lrc, OnceCell};
 use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
 use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
@@ -130,7 +130,7 @@ pub struct ParseSess {
     /// operation token that followed it, but that the parser cannot identify without further
     /// analysis.
     pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
-    pub injected_crate_name: Once<Symbol>,
+    pub injected_crate_name: OnceCell<Symbol>,
     pub gated_spans: GatedSpans,
     pub symbol_gallery: SymbolGallery,
     /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
@@ -156,7 +156,7 @@ impl ParseSess {
             source_map,
             buffered_lints: Lock::new(vec![]),
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
-            injected_crate_name: Once::new(),
+            injected_crate_name: OnceCell::new(),
             gated_spans: GatedSpans::default(),
             symbol_gallery: SymbolGallery::default(),
             reached_eof: Lock::new(false),
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 143401dd3b6..f2f02cb6494 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::jobserver::{self, Client};
 use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef};
 use rustc_data_structures::sync::{
-    self, AtomicU64, AtomicUsize, Lock, Lrc, Once, OneThread, Ordering, Ordering::SeqCst,
+    self, AtomicU64, AtomicUsize, Lock, Lrc, OnceCell, OneThread, Ordering, Ordering::SeqCst,
 };
 use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
 use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
@@ -77,25 +77,25 @@ pub struct Session {
     /// (sub)diagnostics that have been set once, but should not be set again,
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
-    pub crate_types: Once<Vec<CrateType>>,
+    crate_types: OnceCell<Vec<CrateType>>,
     /// The `crate_disambiguator` is constructed out of all the `-C metadata`
     /// arguments passed to the compiler. Its value together with the crate-name
     /// forms a unique global identifier for the crate. It is used to allow
     /// multiple crates with the same name to coexist. See the
     /// `rustc_codegen_llvm::back::symbol_names` module for more information.
-    pub crate_disambiguator: Once<CrateDisambiguator>,
+    pub crate_disambiguator: OnceCell<CrateDisambiguator>,
 
-    features: Once<rustc_feature::Features>,
+    features: OnceCell<rustc_feature::Features>,
 
     /// The maximum recursion limit for potentially infinitely recursive
     /// operations such as auto-dereference and monomorphization.
-    pub recursion_limit: Once<usize>,
+    pub recursion_limit: OnceCell<usize>,
 
     /// The maximum length of types during monomorphization.
-    pub type_length_limit: Once<usize>,
+    pub type_length_limit: OnceCell<usize>,
 
     /// The maximum blocks a const expression can evaluate.
-    pub const_eval_limit: Once<usize>,
+    pub const_eval_limit: OnceCell<usize>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
     /// Used for incremental compilation tests. Will only be populated if
@@ -244,7 +244,27 @@ impl Session {
     }
 
     pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
-        *self.crate_disambiguator.get()
+        self.crate_disambiguator.get().copied().unwrap()
+    }
+
+    pub fn crate_types(&self) -> &[CrateType] {
+        self.crate_types.get().unwrap().as_slice()
+    }
+
+    pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
+        self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
+    }
+
+    pub fn recursion_limit(&self) -> usize {
+        self.recursion_limit.get().copied().unwrap()
+    }
+
+    pub fn type_length_limit(&self) -> usize {
+        self.type_length_limit.get().copied().unwrap()
+    }
+
+    pub fn const_eval_limit(&self) -> usize {
+        self.const_eval_limit.get().copied().unwrap()
     }
 
     pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
@@ -500,11 +520,14 @@ impl Session {
     /// dependency tracking. Use tcx.features() instead.
     #[inline]
     pub fn features_untracked(&self) -> &rustc_feature::Features {
-        self.features.get()
+        self.features.get().unwrap()
     }
 
     pub fn init_features(&self, features: rustc_feature::Features) {
-        self.features.set(features);
+        match self.features.set(features) {
+            Ok(()) => {}
+            Err(_) => panic!("`features` was initialized twice"),
+        }
     }
 
     /// Calculates the flavor of LTO to use for this compilation.
@@ -1208,12 +1231,12 @@ pub fn build_session_with_source_map(
         local_crate_source_file,
         working_dir,
         one_time_diagnostics: Default::default(),
-        crate_types: Once::new(),
-        crate_disambiguator: Once::new(),
-        features: Once::new(),
-        recursion_limit: Once::new(),
-        type_length_limit: Once::new(),
-        const_eval_limit: Once::new(),
+        crate_types: OnceCell::new(),
+        crate_disambiguator: OnceCell::new(),
+        features: OnceCell::new(),
+        recursion_limit: OnceCell::new(),
+        type_length_limit: OnceCell::new(),
+        const_eval_limit: OnceCell::new(),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
         prof,
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 2aef8aaf0e3..b1c6815c741 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1000,12 +1000,15 @@ trait InferCtxtPrivExt<'tcx> {
         trait_ref: &ty::PolyTraitRef<'tcx>,
     );
 
-    fn mk_obligation_for_def_id(
+    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
+    /// `trait_ref`.
+    ///
+    /// For this to work, `new_self_ty` must have no escaping bound variables.
+    fn mk_trait_obligation_with_new_self_ty(
         &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+        new_self_ty: Ty<'tcx>,
     ) -> PredicateObligation<'tcx>;
 
     fn maybe_report_ambiguity(
@@ -1380,16 +1383,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
     }
 
-    fn mk_obligation_for_def_id(
+    fn mk_trait_obligation_with_new_self_ty(
         &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+        new_self_ty: Ty<'tcx>,
     ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate(self.tcx))
+        assert!(!new_self_ty.has_escaping_bound_vars());
+
+        let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef {
+            substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]),
+            ..*tr
+        });
+
+        Obligation::new(
+            ObligationCause::dummy(),
+            param_env,
+            trait_ref.without_const().to_predicate(self.tcx),
+        )
     }
 
     fn maybe_report_ambiguity(
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 0760bd523b7..5c85855535e 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -532,14 +532,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         };
         let msg = format!("use parentheses to call the {}", callable);
 
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
+        // `mk_trait_obligation_with_new_self_ty` only works for types with no escaping bound
+        // variables, so bail out if we have any.
+        let output_ty = match output_ty.no_bound_vars() {
+            Some(ty) => ty,
+            None => return,
+        };
+
+        let new_obligation =
+            self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_ref, output_ty);
 
-        match self.evaluate_obligation(&obligation) {
+        match self.evaluate_obligation(&new_obligation) {
             Ok(
                 EvaluationResult::EvaluatedToOk
                 | EvaluationResult::EvaluatedToOkModuloRegions
@@ -694,7 +697,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
     ) {
-        let trait_ref = trait_ref.skip_binder();
         let span = obligation.cause.span;
 
         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -705,17 +707,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 return;
             }
 
-            let mut trait_type = trait_ref.self_ty();
+            let mut suggested_ty = trait_ref.self_ty();
 
             for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
+                if let ty::Ref(_, inner_ty, _) = suggested_ty.kind {
+                    suggested_ty = inner_ty;
 
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
+                    let new_obligation = self.mk_trait_obligation_with_new_self_ty(
                         obligation.param_env,
+                        trait_ref,
+                        suggested_ty,
                     );
 
                     if self.predicate_may_hold(&new_obligation) {
@@ -782,20 +783,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     return;
                 }
 
-                let trait_type = match mutability {
+                let suggested_ty = match mutability {
                     hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
                     hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
                 };
 
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
+                let new_obligation = self.mk_trait_obligation_with_new_self_ty(
                     obligation.param_env,
+                    &trait_ref,
+                    suggested_ty,
                 );
-
-                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
-                {
+                let suggested_ty_would_satisfy_obligation = self
+                    .evaluate_obligation_no_overflow(&new_obligation)
+                    .must_apply_modulo_regions();
+                if suggested_ty_would_satisfy_obligation {
                     let sp = self
                         .tcx
                         .sess
@@ -812,7 +813,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         err.note(&format!(
                             "`{}` is implemented for `{:?}`, but not for `{:?}`",
                             trait_ref.print_only_trait_path(),
-                            trait_type,
+                            suggested_ty,
                             trait_ref.skip_binder().self_ty(),
                         ));
                     }
@@ -1875,7 +1876,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     }
 
     fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
+        let current_limit = self.tcx.sess.recursion_limit();
         let suggested_limit = current_limit * 2;
         err.help(&format!(
             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
@@ -1891,7 +1892,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         span: Span,
     ) {
         debug!(
-            "suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
+            "suggest_await_before_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
             obligation,
             span,
             trait_ref,
@@ -1946,16 +1947,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 );
 
                 debug!(
-                    "suggest_await_befor_try: normalized_projection_type {:?}",
+                    "suggest_await_before_try: normalized_projection_type {:?}",
                     self.resolve_vars_if_possible(&normalized_ty)
                 );
-                let try_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.def_id(),
-                    normalized_ty,
-                    obligation.cause.clone(),
+                let try_obligation = self.mk_trait_obligation_with_new_self_ty(
                     obligation.param_env,
+                    trait_ref,
+                    normalized_ty,
                 );
-                debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation);
+                debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
                 if self.predicate_may_hold(&try_obligation) && impls_future {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                         if snippet.ends_with('?') {
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index 9b63cbdd83c..914485fd408 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -332,7 +332,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
+                        let recursion_limit = self.tcx().sess.recursion_limit();
                         if self.depth >= recursion_limit {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
@@ -520,7 +520,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             );
 
             // But for now, let's classify this as an overflow:
-            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+            let recursion_limit = selcx.tcx().sess.recursion_limit();
             let obligation =
                 Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
             selcx.infcx().report_overflow_error(&obligation, false);
@@ -814,7 +814,7 @@ fn project_type<'cx, 'tcx>(
 ) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
     debug!("project(obligation={:?})", obligation);
 
-    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
+    let recursion_limit = selcx.tcx().sess.recursion_limit();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
         return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 3b985a4b150..008ca8d526d 100644
--- a/src/librustc_trait_selection/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -108,7 +108,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
+                        let recursion_limit = self.tcx().sess.recursion_limit();
                         if self.anon_depth >= recursion_limit {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs
index 6110d6470df..b402aba65cd 100644
--- a/src/librustc_trait_selection/traits/select.rs
+++ b/src/librustc_trait_selection/traits/select.rs
@@ -919,8 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &Obligation<'tcx, T>,
         error_obligation: &Obligation<'tcx, V>,
     ) -> Result<(), OverflowError> {
-        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
-        if obligation.recursion_depth >= recursion_limit {
+        if obligation.recursion_depth >= self.infcx.tcx.sess.recursion_limit() {
             match self.query_mode {
                 TraitQueryMode::Standard => {
                     self.infcx().report_overflow_error(error_obligation, true);
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 08475d6a09d..fb9c0d7f990 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
 ) -> Result<(), NoSolution> {
     debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
 
-    if depth >= *tcx.sess.recursion_limit.get() {
+    if depth >= tcx.sess.recursion_limit() {
         constraints.overflows.push(ty);
         return Ok(());
     }
diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs
index 97994b465b5..e94a47f079a 100644
--- a/src/librustc_ty/needs_drop.rs
+++ b/src/librustc_ty/needs_drop.rs
@@ -43,14 +43,13 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
     ) -> Self {
         let mut seen_tys = FxHashSet::default();
         seen_tys.insert(ty);
-        let recursion_limit = *tcx.sess.recursion_limit.get();
         Self {
             tcx,
             param_env,
             seen_tys,
             query_ty: ty,
             unchecked_tys: vec![(ty, 0)],
-            recursion_limit,
+            recursion_limit: tcx.sess.recursion_limit(),
             adt_components,
         }
     }
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 8ca08610906..d4c01a82e0a 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             return Some((self.cur_ty, 0));
         }
 
-        if self.steps.len() >= *tcx.sess.recursion_limit.get() {
+        if self.steps.len() >= tcx.sess.recursion_limit() {
             if !self.silence_errors {
                 report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
             }
@@ -236,7 +236,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
 
 pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
     // We've reached the recursion limit, error gracefully.
-    let suggested_limit = *tcx.sess.recursion_limit.get() * 2;
+    let suggested_limit = tcx.sess.recursion_limit() * 2;
     let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
     let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
     let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 2a1c6b895ce..a324bd03eca 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -887,7 +887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
         coerce
             .autoderef(rustc_span::DUMMY_SP, expr_ty)
-            .find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps))
+            .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
     }
 
     /// Given some expressions, their known unified type and another expression,
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index fc7a9c1d59b..700b9359d06 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -1,16 +1,15 @@
 use crate::check::FnCtxt;
 use rustc_infer::infer::InferOk;
 use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause};
+use rustc_trait_selection::traits::ObligationCause;
 
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem};
+use rustc_hir::lang_items::CloneTraitLangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
-use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut};
+use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             _ if sp == expr.span && !is_macro => {
-                // Check for `Deref` implementations by constructing a predicate to
-                // prove: `<T as Deref>::Output == U`
-                let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp));
-                let item_def_id = self
-                    .tcx
-                    .associated_items(deref_trait)
-                    .in_definition_order()
-                    .find(|item| item.kind == ty::AssocKind::Type)
-                    .unwrap()
-                    .def_id;
-                let predicate =
-                    ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate {
-                        // `<T as Deref>::Output`
-                        projection_ty: ty::ProjectionTy {
-                            // `T`
-                            substs: self.tcx.intern_substs(&[checked_ty.into()]),
-                            // `Deref::Output`
-                            item_def_id,
-                        },
-                        // `U`
-                        ty: expected,
-                    }))
-                    .to_predicate(self.tcx);
-                let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
-                let impls_deref = self.infcx.predicate_may_hold(&obligation);
-
-                // For a suggestion to make sense, the type would need to be `Copy`.
-                let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);
-
-                if is_copy && impls_deref {
-                    if let Ok(code) = sm.span_to_snippet(sp) {
-                        let message = if checked_ty.is_region_ptr() {
-                            "consider dereferencing the borrow"
-                        } else {
-                            "consider dereferencing the type"
-                        };
-                        let suggestion = if is_struct_pat_shorthand_field {
-                            format!("{}: *{}", code, code)
-                        } else {
-                            format!("*{}", code)
-                        };
-                        return Some((sp, message, suggestion, Applicability::MachineApplicable));
+                if let Some(steps) = self.deref_steps(checked_ty, expected) {
+                    if steps == 1 {
+                        // For a suggestion to make sense, the type would need to be `Copy`.
+                        if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) {
+                            if let Ok(code) = sm.span_to_snippet(sp) {
+                                let message = if checked_ty.is_region_ptr() {
+                                    "consider dereferencing the borrow"
+                                } else {
+                                    "consider dereferencing the type"
+                                };
+                                let suggestion = if is_struct_pat_shorthand_field {
+                                    format!("{}: *{}", code, code)
+                                } else {
+                                    format!("*{}", code)
+                                };
+                                return Some((
+                                    sp,
+                                    message,
+                                    suggestion,
+                                    Applicability::MachineApplicable,
+                                ));
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 2cb3347135c..b1e0ab9ca64 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -3,12 +3,14 @@
 	font-family: 'Fira Sans';
 	font-style: normal;
 	font-weight: 400;
+	font-display: optional;
 	src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
 }
 @font-face {
 	font-family: 'Fira Sans';
 	font-style: normal;
 	font-weight: 500;
+	font-display: optional;
 	src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
 }
 
@@ -17,18 +19,23 @@
 	font-family: 'Source Serif Pro';
 	font-style: normal;
 	font-weight: 400;
+	/* The difference for body text without this font is greater than other fonts,
+	 * so the 0~100ms block of fallback is preferred over optional, for legibility. */
+	font-display: fallback;
 	src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff');
 }
 @font-face {
 	font-family: 'Source Serif Pro';
 	font-style: italic;
 	font-weight: 400;
+	font-display: optional;
 	src: local('Source Serif Pro Italic'), url("SourceSerifPro-It.ttf.woff") format('woff');
 }
 @font-face {
 	font-family: 'Source Serif Pro';
 	font-style: normal;
 	font-weight: 700;
+	font-display: optional;
 	src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff');
 }
 
@@ -37,6 +44,7 @@
 	font-family: 'Source Code Pro';
 	font-style: normal;
 	font-weight: 400;
+	font-display: optional;
 	/* Avoid using locally installed font because bad versions are in circulation:
 	 * see https://github.com/rust-lang/rust/issues/24355 */
 	src: url("SourceCodePro-Regular.woff") format('woff');
@@ -45,6 +53,7 @@
 	font-family: 'Source Code Pro';
 	font-style: normal;
 	font-weight: 600;
+	font-display: optional;
 	src: url("SourceCodePro-Semibold.woff") format('woff');
 }
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 05f3b598ecd..adb7fc3eb9c 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -431,6 +431,43 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
 
         look_for_tests(&cx, &dox, &item, true);
 
+        // find item's parent to resolve `Self` in item's docs below
+        let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| {
+            let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
+            let item_parent = self.cx.tcx.hir().find(parent_hir);
+            match item_parent {
+                Some(hir::Node::Item(hir::Item {
+                    kind:
+                        hir::ItemKind::Impl {
+                            self_ty:
+                                hir::Ty {
+                                    kind:
+                                        hir::TyKind::Path(hir::QPath::Resolved(
+                                            _,
+                                            hir::Path { segments, .. },
+                                        )),
+                                    ..
+                                },
+                            ..
+                        },
+                    ..
+                })) => segments.first().and_then(|seg| Some(seg.ident.to_string())),
+                Some(hir::Node::Item(hir::Item {
+                    ident, kind: hir::ItemKind::Enum(..), ..
+                }))
+                | Some(hir::Node::Item(hir::Item {
+                    ident, kind: hir::ItemKind::Struct(..), ..
+                }))
+                | Some(hir::Node::Item(hir::Item {
+                    ident, kind: hir::ItemKind::Union(..), ..
+                }))
+                | Some(hir::Node::Item(hir::Item {
+                    ident, kind: hir::ItemKind::Trait(..), ..
+                })) => Some(ident.to_string()),
+                _ => None,
+            }
+        });
+
         for (ori_link, link_range) in markdown_links(&dox) {
             // Bail early for real links.
             if ori_link.contains('/') {
@@ -467,7 +504,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
             };
             let (res, fragment) = {
                 let mut kind = None;
-                let path_str = if let Some(prefix) =
+                let mut path_str = if let Some(prefix) =
                     ["struct@", "enum@", "type@", "trait@", "union@"]
                         .iter()
                         .find(|p| link.starts_with(**p))
@@ -521,6 +558,15 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                 let base_node =
                     if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
 
+                let resolved_self;
+                // replace `Self` with suitable item's parent name
+                if path_str.starts_with("Self::") {
+                    if let Some(ref name) = parent_name {
+                        resolved_self = format!("{}::{}", name, &path_str[6..]);
+                        path_str = &resolved_self;
+                    }
+                }
+
                 match kind {
                     Some(ns @ ValueNS) => {
                         match self.resolve(
@@ -529,7 +575,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                             &current_item,
                             base_node,
                             &extra_fragment,
-                            None,
+                            Some(&item),
                         ) {
                             Ok(res) => res,
                             Err(ErrorKind::ResolutionFailure) => {
@@ -552,7 +598,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                             &current_item,
                             base_node,
                             &extra_fragment,
-                            None,
+                            Some(&item),
                         ) {
                             Ok(res) => res,
                             Err(ErrorKind::ResolutionFailure) => {
@@ -577,7 +623,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                                 &current_item,
                                 base_node,
                                 &extra_fragment,
-                                None,
+                                Some(&item),
                             ) {
                                 Err(ErrorKind::AnchorFailure(msg)) => {
                                     anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 8e743ace99b..deb9eb5b4b0 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -882,7 +882,7 @@ impl f32 {
     /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
     /// less than `min`. Otherwise this returns `self`.
     ///
-    /// Not that this function returns NaN if the initial value was NaN as
+    /// Note that this function returns NaN if the initial value was NaN as
     /// well.
     ///
     /// # Panics
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index fe64d27b1ef..b79e550ed26 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -884,7 +884,7 @@ impl f64 {
     /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
     /// less than `min`. Otherwise this returns `self`.
     ///
-    /// Not that this function returns NaN if the initial value was NaN as
+    /// Note that this function returns NaN if the initial value was NaN as
     /// well.
     ///
     /// # Panics
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index e2092cfefa3..89dd9fb9b2c 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -2,4 +2,16 @@
 
 #[doc(inline)]
 #[stable(feature = "futures_api", since = "1.36.0")]
-pub use core::future::*;
+pub use core::future::Future;
+
+#[doc(inline)]
+#[unstable(feature = "gen_future", issue = "50547")]
+pub use core::future::{from_generator, get_context, ResumeTy};
+
+#[doc(inline)]
+#[unstable(feature = "future_readiness_fns", issue = "70921")]
+pub use core::future::{pending, ready, Pending, Ready};
+
+#[doc(inline)]
+#[unstable(feature = "into_future", issue = "67644")]
+pub use core::future::IntoFuture;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index ac07af5e278..cc3e613fa3d 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -266,12 +266,15 @@
 #![feature(external_doc)]
 #![feature(fn_traits)]
 #![feature(format_args_nl)]
+#![feature(future_readiness_fns)]
+#![feature(gen_future)]
 #![feature(generator_trait)]
 #![feature(global_asm)]
 #![feature(hash_raw_entry)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
 #![feature(int_error_matching)]
+#![feature(into_future)]
 #![feature(integer_atomics)]
 #![feature(lang_items)]
 #![feature(libc)]
diff --git a/src/test/incremental/issue-72386.rs b/src/test/incremental/issue-72386.rs
new file mode 100644
index 00000000000..3dc7f502a59
--- /dev/null
+++ b/src/test/incremental/issue-72386.rs
@@ -0,0 +1,22 @@
+// revisions: rpass1 cfail1 rpass3
+// only-x86_64
+// Regression test for issue #72386
+// Checks that we don't ICE when switching to an invalid register
+// and back again
+
+#![feature(asm)]
+
+#[cfg(any(rpass1, rpass3))]
+fn main() {
+    unsafe {
+        asm!("nop")
+    }
+}
+
+#[cfg(cfail1)]
+fn main() {
+    unsafe {
+        asm!("nop",out("invalid_reg")_)
+        //[cfail1]~^ ERROR invalid register
+    }
+}
diff --git a/src/test/rustdoc/intra-link-self.rs b/src/test/rustdoc/intra-link-self.rs
index acf975f5c73..97752d5cfcb 100644
--- a/src/test/rustdoc/intra-link-self.rs
+++ b/src/test/rustdoc/intra-link-self.rs
@@ -1,5 +1,7 @@
 #![crate_name = "foo"]
 
+// ignore-tidy-linelength
+
 // @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
 // @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
 
@@ -27,3 +29,89 @@ impl Bar {
         unimplemented!()
     }
 }
+
+pub struct MyStruct {
+    // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#structfield.struct_field'
+
+    /// [`struct_field`]
+    ///
+    /// [`struct_field`]: Self::struct_field
+    pub struct_field: u8,
+}
+
+pub enum MyEnum {
+    // @has foo/enum.MyEnum.html '//a/@href' '../foo/enum.MyEnum.html#EnumVariant.v'
+
+    /// [`EnumVariant`]
+    ///
+    /// [`EnumVariant`]: Self::EnumVariant
+    EnumVariant,
+}
+
+pub union MyUnion {
+    // @has foo/union.MyUnion.html '//a/@href' '../foo/union.MyUnion.html#structfield.union_field'
+
+    /// [`union_field`]
+    ///
+    /// [`union_field`]: Self::union_field
+    pub union_field: f32,
+}
+
+pub trait MyTrait {
+    // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedtype.AssoType'
+
+    /// [`AssoType`]
+    ///
+    /// [`AssoType`]: Self::AssoType
+    type AssoType;
+
+    // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedconstant.ASSO_CONST'
+
+    /// [`ASSO_CONST`]
+    ///
+    /// [`ASSO_CONST`]: Self::ASSO_CONST
+    const ASSO_CONST: i32 = 1;
+
+    // @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#method.asso_fn'
+
+    /// [`asso_fn`]
+    ///
+    /// [`asso_fn`]: Self::asso_fn
+    fn asso_fn() {}
+}
+
+impl MyStruct {
+    // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.for_impl'
+
+    /// [`for_impl`]
+    ///
+    /// [`for_impl`]: Self::for_impl
+    pub fn for_impl() {
+        unimplemented!()
+    }
+}
+
+impl MyTrait for MyStruct {
+    // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType'
+
+    /// [`AssoType`]
+    ///
+    /// [`AssoType`]: Self::AssoType
+    type AssoType = u32;
+
+    // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST'
+
+    /// [`ASSO_CONST`]
+    ///
+    /// [`ASSO_CONST`]: Self::ASSO_CONST
+    const ASSO_CONST: i32 = 10;
+
+    // @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.asso_fn'
+
+    /// [`asso_fn`]
+    ///
+    /// [`asso_fn`]: Self::asso_fn
+    fn asso_fn() {
+        unimplemented!()
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 0faa9090f4e..9bce274027e 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -1,3 +1,6 @@
+// compile-flags: -Zsave-analysis
+// This is also a regression test for #69415 and the above flag is needed.
+
 #![feature(untagged_unions)]
 
 trait Tr1 { type As1: Copy; }
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index bfa59d83c82..7f2704e1bc3 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -1,5 +1,5 @@
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:12:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:15:22
    |
 LL |     type A: Iterator<Item: Copy>;
    |                      ^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     type A: Iterator<Item: Copy>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:15:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:18:22
    |
 LL |     type B: Iterator<Item: 'static>;
    |                      ^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     type B: Iterator<Item: 'static>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:19:20
+  --> $DIR/feature-gate-associated_type_bounds.rs:22:20
    |
 LL | struct _St1<T: Tr1<As1: Tr2>> {
    |                    ^^^^^^^^
@@ -26,7 +26,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:26:18
+  --> $DIR/feature-gate-associated_type_bounds.rs:29:18
    |
 LL | enum _En1<T: Tr1<As1: Tr2>> {
    |                  ^^^^^^^^
@@ -35,7 +35,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:33:19
+  --> $DIR/feature-gate-associated_type_bounds.rs:36:19
    |
 LL | union _Un1<T: Tr1<As1: Tr2>> {
    |                   ^^^^^^^^
@@ -44,7 +44,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:40:37
+  --> $DIR/feature-gate-associated_type_bounds.rs:43:37
    |
 LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    |                                     ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:43:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:46:22
    |
 LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    |                      ^^^^^^^^^
@@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:45:26
+  --> $DIR/feature-gate-associated_type_bounds.rs:48:26
    |
 LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    |                          ^^^^^^^^^
@@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:48:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:51:24
    |
 LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    |                        ^^^^^^^^^
@@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:51:31
+  --> $DIR/feature-gate-associated_type_bounds.rs:54:31
    |
 LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    |                               ^^^^^^^^^
@@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:54:23
+  --> $DIR/feature-gate-associated_type_bounds.rs:57:23
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |                       ^^^^^^^^^
@@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:60:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:63:24
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |                        ^^^^^^^^^
@@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:67:21
+  --> $DIR/feature-gate-associated_type_bounds.rs:70:21
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |                     ^^^^^^^^^
@@ -116,7 +116,7 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:54:14
+  --> $DIR/feature-gate-associated_type_bounds.rs:57:14
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |              ^^^^^^^^^^^^^^^^^^^
@@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:60:15
+  --> $DIR/feature-gate-associated_type_bounds.rs:63:15
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |               ^^^^^^^^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:67:12
+  --> $DIR/feature-gate-associated_type_bounds.rs:70:12
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |            ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/issues/issue-72455.rs
new file mode 100644
index 00000000000..b6c3bb22287
--- /dev/null
+++ b/src/test/ui/issues/issue-72455.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+pub trait ResultExt {
+    type Ok;
+    fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+    E: std::error::Error,
+{
+    type Ok = O;
+    fn err_eprint_and_ignore(self) -> Option<O>
+    where
+        Self: ,
+    {
+        match self {
+            Err(e) => {
+                eprintln!("{}", e);
+                None
+            }
+            Ok(o) => Some(o),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index 7414a7cc24c..f7affdbf1b4 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -8,7 +8,6 @@ LL |     foo(String::new());
    |     ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
    |
    = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
-   = note: `std::convert::From<std::string::String>` is implemented for `&mut str`, but not for `&str`
    = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
 
 error: aborting due to previous error
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.rs b/src/test/ui/suggestions/issue-71394-no-from-impl.rs
new file mode 100644
index 00000000000..9ffcc3f7bc1
--- /dev/null
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let data: &[u8] = &[0; 10];
+    let _: &[i8] = data.into();
+    //~^ ERROR the trait bound `&[i8]: std::convert::From<&[u8]>` is not satisfied
+}
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
new file mode 100644
index 00000000000..84c73c2f67e
--- /dev/null
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `&[i8]: std::convert::From<&[u8]>` is not satisfied
+  --> $DIR/issue-71394-no-from-impl.rs:3:25
+   |
+LL |     let _: &[i8] = data.into();
+   |                         ^^^^ the trait `std::convert::From<&[u8]>` is not implemented for `&[i8]`
+   |
+   = note: required because of the requirements on the impl of `std::convert::Into<&[i8]>` for `&[u8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 5300fd2215b..3ad3d5aee4d 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -71,7 +71,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute]
 fn is_executable(cx: &LateContext<'_, '_>) -> bool {
     use rustc_session::config::CrateType;
 
-    cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t {
+    cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t {
         CrateType::Executable => true,
         _ => false,
     })
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 988a226706d..72437e07004 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -39,6 +39,19 @@ MAINTAINERS = {
     'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'},
 }
 
+LABELS = {
+    'miri': ['A-miri', 'C-bug'],
+    'rls': ['A-rls', 'C-bug'],
+    'rustfmt': ['C-bug'],
+    'book': ['C-bug'],
+    'nomicon': ['C-bug'],
+    'reference': ['C-bug'],
+    'rust-by-example': ['C-bug'],
+    'embedded-book': ['C-bug'],
+    'edition-guide': ['C-bug'],
+    'rustc-dev-guide': ['C-bug'],
+}
+
 REPOS = {
     'miri': 'https://github.com/rust-lang/miri',
     'rls': 'https://github.com/rust-lang/rls',
@@ -132,6 +145,7 @@ def issue(
     assignees,
     relevant_pr_number,
     relevant_pr_user,
+    labels,
 ):
     # Open an issue about the toolstate failure.
     if status == 'test-fail':
@@ -155,6 +169,7 @@ def issue(
         )),
         'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
         'assignees': list(assignees),
+        'labels': labels,
     })
     print("Creating issue:\n{}".format(request))
     response = urllib2.urlopen(urllib2.Request(
@@ -235,7 +250,7 @@ def update_latest(
                 try:
                     issue(
                         tool, create_issue_for_status, MAINTAINERS.get(tool, ''),
-                        relevant_pr_number, relevant_pr_user,
+                        relevant_pr_number, relevant_pr_user, LABELS.get(tool, ''),
                     )
                 except urllib2.HTTPError as e:
                     # network errors will simply end up not creating an issue, but that's better
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index d3c7b7a068b..61389028cc7 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -128,6 +128,7 @@ const WHITELIST: &[&str] = &[
     "miniz_oxide",
     "nodrop",
     "num_cpus",
+    "once_cell",
     "opaque-debug",
     "parking_lot",
     "parking_lot_core",
diff --git a/triagebot.toml b/triagebot.toml
index 2210a8ff8e6..f12d5163763 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -37,5 +37,9 @@ label = "ICEBreaker-Cleanup-Crew"
 [prioritize]
 label = "I-prioritize"
 prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]
-priority_labels = "P-*"
+exclude_labels = [
+    "P-*",
+    "T-infra",
+    "T-release",
+]
 zulip_stream = 227806