diff --git a/Cargo.lock b/Cargo.lock
index b3fa511839b1d..a55ef7b61436e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -582,6 +582,19 @@ dependencies = [
 name = "clippy-mini-macro-test"
 version = "0.2.0"
 
+[[package]]
+name = "clippy_dev"
+version = "0.0.1"
+dependencies = [
+ "bytecount",
+ "clap",
+ "itertools 0.9.0",
+ "opener",
+ "regex",
+ "shell-escape",
+ "walkdir",
+]
+
 [[package]]
 name = "clippy_lints"
 version = "0.1.53"
diff --git a/Cargo.toml b/Cargo.toml
index 02011357eac9b..327afe35c2fb9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ members = [
   "src/rustdoc-json-types",
   "src/tools/cargotest",
   "src/tools/clippy",
+  "src/tools/clippy/clippy_dev",
   "src/tools/compiletest",
   "src/tools/error_index_generator",
   "src/tools/linkchecker",
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 259e540c6125e..2661afd7ffc3b 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -104,7 +104,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     // Fortunately, we just checked that this isn't the case.
     let path = dep_graph_path_from(&sess.incr_comp_session_dir());
     let report_incremental_info = sess.opts.debugging_opts.incremental_info;
-    let expected_hash = sess.opts.dep_tracking_hash();
+    let expected_hash = sess.opts.dep_tracking_hash(false);
 
     let mut prev_work_products = FxHashMap::default();
     let nightly_build = sess.is_nightly_build();
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index d558af3c1d558..1484088837a4b 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -219,7 +219,7 @@ pub fn build_dep_graph(
     }
 
     // First encode the commandline arguments hash
-    if let Err(err) = sess.opts.dep_tracking_hash().encode(&mut encoder) {
+    if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) {
         sess.err(&format!(
             "failed to write dependency graph hash `{}`: {}",
             path_buf.display(),
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 9685d21762b7c..d8c1a7a268220 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -19,6 +19,7 @@ use rustc_span::symbol::sym;
 use rustc_span::SourceFileHashAlgorithm;
 use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
 use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel};
+
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
 use std::num::NonZeroUsize;
@@ -74,6 +75,27 @@ fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
     BTreeMap::from_iter(entries.into_iter())
 }
 
+fn assert_same_clone(x: &Options) {
+    assert_eq!(x.dep_tracking_hash(true), x.clone().dep_tracking_hash(true));
+    assert_eq!(x.dep_tracking_hash(false), x.clone().dep_tracking_hash(false));
+}
+
+fn assert_same_hash(x: &Options, y: &Options) {
+    assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
+    assert_eq!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
+    // Check clone
+    assert_same_clone(x);
+    assert_same_clone(y);
+}
+
+fn assert_different_hash(x: &Options, y: &Options) {
+    assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
+    assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
+    // Check clone
+    assert_same_clone(x);
+    assert_same_clone(y);
+}
+
 // When the user supplies --test we should implicitly supply --cfg test
 #[test]
 fn test_switch_implies_cfg_test() {
@@ -130,14 +152,9 @@ fn test_output_types_tracking_hash_different_paths() {
     v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
     v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
 
-    assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-    assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
+    assert_different_hash(&v1, &v2);
+    assert_different_hash(&v1, &v3);
+    assert_different_hash(&v2, &v3);
 }
 
 #[test]
@@ -155,10 +172,7 @@ fn test_output_types_tracking_hash_different_construction_order() {
         (OutputType::Exe, Some(PathBuf::from("./some/thing"))),
     ]);
 
-    assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
+    assert_same_hash(&v1, &v2);
 }
 
 #[test]
@@ -182,14 +196,9 @@ fn test_externs_tracking_hash_different_construction_order() {
         (String::from("d"), new_public_extern_entry(vec!["f", "e"])),
     ]));
 
-    assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
-    assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
+    assert_same_hash(&v1, &v2);
+    assert_same_hash(&v1, &v3);
+    assert_same_hash(&v2, &v3);
 }
 
 #[test]
@@ -219,14 +228,9 @@ fn test_lints_tracking_hash_different_values() {
         (String::from("d"), Level::Deny),
     ];
 
-    assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-    assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
+    assert_different_hash(&v1, &v2);
+    assert_different_hash(&v1, &v3);
+    assert_different_hash(&v2, &v3);
 }
 
 #[test]
@@ -248,11 +252,7 @@ fn test_lints_tracking_hash_different_construction_order() {
         (String::from("d"), Level::Forbid),
     ];
 
-    assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
+    assert_same_hash(&v1, &v2);
 }
 
 #[test]
@@ -292,15 +292,9 @@ fn test_search_paths_tracking_hash_different_order() {
     v4.search_paths.push(SearchPath::from_cli_opt("dependency=ghi", JSON));
     v4.search_paths.push(SearchPath::from_cli_opt("framework=jkl", JSON));
 
-    assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-    assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
+    assert_same_hash(&v1, &v2);
+    assert_same_hash(&v1, &v3);
+    assert_same_hash(&v1, &v4);
 }
 
 #[test]
@@ -338,15 +332,9 @@ fn test_native_libs_tracking_hash_different_values() {
         (String::from("c"), None, NativeLibKind::Unspecified),
     ];
 
-    assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-    assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
+    assert_different_hash(&v1, &v2);
+    assert_different_hash(&v1, &v3);
+    assert_different_hash(&v1, &v4);
 }
 
 #[test]
@@ -374,14 +362,9 @@ fn test_native_libs_tracking_hash_different_order() {
         (String::from("b"), None, NativeLibKind::Framework),
     ];
 
-    assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
-    assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
-    assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash());
-
-    // Check clone
-    assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-    assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-    assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
+    assert_same_hash(&v1, &v2);
+    assert_same_hash(&v1, &v3);
+    assert_same_hash(&v2, &v3);
 }
 
 #[test]
@@ -391,8 +374,9 @@ fn test_codegen_options_tracking_hash() {
 
     macro_rules! untracked {
         ($name: ident, $non_default_value: expr) => {
+            assert_ne!(opts.cg.$name, $non_default_value);
             opts.cg.$name = $non_default_value;
-            assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
+            assert_same_hash(&reference, &opts);
         };
     }
 
@@ -416,8 +400,9 @@ fn test_codegen_options_tracking_hash() {
     macro_rules! tracked {
         ($name: ident, $non_default_value: expr) => {
             opts = reference.clone();
+            assert_ne!(opts.cg.$name, $non_default_value);
             opts.cg.$name = $non_default_value;
-            assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
+            assert_different_hash(&reference, &opts);
         };
     }
 
@@ -454,6 +439,32 @@ fn test_codegen_options_tracking_hash() {
     tracked!(target_feature, String::from("all the features, all of them"));
 }
 
+#[test]
+fn test_top_level_options_tracked_no_crate() {
+    let reference = Options::default();
+    let mut opts;
+
+    macro_rules! tracked {
+        ($name: ident, $non_default_value: expr) => {
+            opts = reference.clone();
+            assert_ne!(opts.$name, $non_default_value);
+            opts.$name = $non_default_value;
+            // The crate hash should be the same
+            assert_eq!(reference.dep_tracking_hash(true), opts.dep_tracking_hash(true));
+            // The incremental hash should be different
+            assert_ne!(reference.dep_tracking_hash(false), opts.dep_tracking_hash(false));
+        };
+    }
+
+    // Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
+    // This list is in alphabetical order.
+    tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
+    tracked!(
+        real_rust_source_base_dir,
+        Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
+    );
+}
+
 #[test]
 fn test_debugging_options_tracking_hash() {
     let reference = Options::default();
@@ -461,8 +472,9 @@ fn test_debugging_options_tracking_hash() {
 
     macro_rules! untracked {
         ($name: ident, $non_default_value: expr) => {
+            assert_ne!(opts.debugging_opts.$name, $non_default_value);
             opts.debugging_opts.$name = $non_default_value;
-            assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
+            assert_same_hash(&reference, &opts);
         };
     }
 
@@ -471,7 +483,7 @@ fn test_debugging_options_tracking_hash() {
     untracked!(ast_json, true);
     untracked!(ast_json_noexpand, true);
     untracked!(borrowck, String::from("other"));
-    untracked!(deduplicate_diagnostics, true);
+    untracked!(deduplicate_diagnostics, false);
     untracked!(dep_tasks, true);
     untracked!(dont_buffer_diagnostics, true);
     untracked!(dump_dep_graph, true);
@@ -515,7 +527,7 @@ fn test_debugging_options_tracking_hash() {
     untracked!(self_profile_events, Some(vec![String::new()]));
     untracked!(span_debug, true);
     untracked!(span_free_formats, true);
-    untracked!(strip, Strip::None);
+    untracked!(strip, Strip::Debuginfo);
     untracked!(terminal_width, Some(80));
     untracked!(threads, 99);
     untracked!(time, true);
@@ -532,8 +544,9 @@ fn test_debugging_options_tracking_hash() {
     macro_rules! tracked {
         ($name: ident, $non_default_value: expr) => {
             opts = reference.clone();
+            assert_ne!(opts.debugging_opts.$name, $non_default_value);
             opts.debugging_opts.$name = $non_default_value;
-            assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
+            assert_different_hash(&reference, &opts);
         };
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 19ae5ce69c136..2ade1bb4f95de 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1617,7 +1617,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .map(Path::new)
             .filter(|_| {
                 // Only spend time on further checks if we have what to translate *to*.
-                sess.real_rust_source_base_dir.is_some()
+                sess.opts.real_rust_source_base_dir.is_some()
             })
             .filter(|virtual_dir| {
                 // Don't translate away `/rustc/$hash` if we're still remapping to it,
@@ -1629,11 +1629,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             debug!(
                 "try_to_translate_virtual_to_real(name={:?}): \
                  virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
-                name, virtual_rust_source_base_dir, sess.real_rust_source_base_dir,
+                name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
             );
 
             if let Some(virtual_dir) = virtual_rust_source_base_dir {
-                if let Some(real_dir) = &sess.real_rust_source_base_dir {
+                if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
                     if let rustc_span::FileName::Real(old_name) = name {
                         if let rustc_span::RealFileName::Named(one_path) = old_name {
                             if let Ok(rest) = one_path.strip_prefix(virtual_dir) {
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index d155276051e4a..4cd126988f91f 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -943,7 +943,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe
         intravisit::walk_crate(&mut collector, tcx.untracked_crate);
 
         let crate_disambiguator = tcx.sess.local_crate_disambiguator();
-        let cmdline_args = tcx.sess.opts.dep_tracking_hash();
+        let cmdline_args = tcx.sess.opts.dep_tracking_hash(true);
         collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
     };
 
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 01bc5cc761ca6..d2e233f67d7bf 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -59,6 +59,13 @@ impl FlagComputation {
     {
         let mut computation = FlagComputation::new();
 
+        // In some cases, there are binders with variables that are unused (e.g., `for<'a> fn(u32)`).
+        // Set the flag to represent the `'a` in this example. Note that if there are late bound types
+        // or consts, this flag will also get set.
+        if !value.bound_vars().is_empty() {
+            computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND;
+        }
+
         f(&mut computation, value.skip_binder());
 
         self.add_flags(computation.flags);
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs
index 2041109eb385f..e0c09d9ed0d8a 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir/src/transform/coverage/spans.rs
@@ -11,8 +11,9 @@ use rustc_middle::mir::{
 use rustc_middle::ty::TyCtxt;
 
 use rustc_span::source_map::original_sp;
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
 
+use std::cell::RefCell;
 use std::cmp::Ordering;
 
 #[derive(Debug, Copy, Clone)]
@@ -67,6 +68,8 @@ impl CoverageStatement {
 #[derive(Debug, Clone)]
 pub(super) struct CoverageSpan {
     pub span: Span,
+    pub expn_span: Span,
+    pub current_macro_or_none: RefCell<Option<Option<Symbol>>>,
     pub bcb: BasicCoverageBlock,
     pub coverage_statements: Vec<CoverageStatement>,
     pub is_closure: bool,
@@ -74,12 +77,20 @@ pub(super) struct CoverageSpan {
 
 impl CoverageSpan {
     pub fn for_fn_sig(fn_sig_span: Span) -> Self {
-        Self { span: fn_sig_span, bcb: START_BCB, coverage_statements: vec![], is_closure: false }
+        Self {
+            span: fn_sig_span,
+            expn_span: fn_sig_span,
+            current_macro_or_none: Default::default(),
+            bcb: START_BCB,
+            coverage_statements: vec![],
+            is_closure: false,
+        }
     }
 
     pub fn for_statement(
         statement: &Statement<'tcx>,
         span: Span,
+        expn_span: Span,
         bcb: BasicCoverageBlock,
         bb: BasicBlock,
         stmt_index: usize,
@@ -94,15 +105,24 @@ impl CoverageSpan {
 
         Self {
             span,
+            expn_span,
+            current_macro_or_none: Default::default(),
             bcb,
             coverage_statements: vec![CoverageStatement::Statement(bb, span, stmt_index)],
             is_closure,
         }
     }
 
-    pub fn for_terminator(span: Span, bcb: BasicCoverageBlock, bb: BasicBlock) -> Self {
+    pub fn for_terminator(
+        span: Span,
+        expn_span: Span,
+        bcb: BasicCoverageBlock,
+        bb: BasicBlock,
+    ) -> Self {
         Self {
             span,
+            expn_span,
+            current_macro_or_none: Default::default(),
             bcb,
             coverage_statements: vec![CoverageStatement::Terminator(bb, span)],
             is_closure: false,
@@ -158,6 +178,38 @@ impl CoverageSpan {
             .collect::<Vec<_>>()
             .join("\n")
     }
+
+    /// If the span is part of a macro, returns the macro name symbol.
+    pub fn current_macro(&self) -> Option<Symbol> {
+        self.current_macro_or_none
+            .borrow_mut()
+            .get_or_insert_with(|| {
+                if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
+                    self.expn_span.ctxt().outer_expn_data().kind
+                {
+                    return Some(current_macro);
+                }
+                None
+            })
+            .map(|symbol| symbol)
+    }
+
+    /// If the span is part of a macro, and the macro is visible (expands directly to the given
+    /// body_span), returns the macro name symbol.
+    pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
+        if let Some(current_macro) = self.current_macro() {
+            if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt()
+                == body_span.ctxt()
+            {
+                return Some(current_macro);
+            }
+        }
+        None
+    }
+
+    pub fn is_macro_expansion(&self) -> bool {
+        self.current_macro().is_some()
+    }
 }
 
 /// Converts the initial set of `CoverageSpan`s (one per MIR `Statement` or `Terminator`) into a
@@ -201,6 +253,9 @@ pub struct CoverageSpans<'a, 'tcx> {
     /// Assigned from `curr_original_span` from the previous iteration.
     prev_original_span: Span,
 
+    /// A copy of the expn_span from the prior iteration.
+    prev_expn_span: Option<Span>,
+
     /// One or more `CoverageSpan`s with the same `Span` but different `BasicCoverageBlock`s, and
     /// no `BasicCoverageBlock` in this list dominates another `BasicCoverageBlock` in the list.
     /// If a new `curr` span also fits this criteria (compared to an existing list of
@@ -255,15 +310,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
             curr_original_span: Span::with_root_ctxt(BytePos(0), BytePos(0)),
             some_prev: None,
             prev_original_span: Span::with_root_ctxt(BytePos(0), BytePos(0)),
+            prev_expn_span: None,
             pending_dups: Vec::new(),
         };
 
         let sorted_spans = coverage_spans.mir_to_initial_sorted_coverage_spans();
 
         coverage_spans.sorted_spans_iter = Some(sorted_spans.into_iter());
-        coverage_spans.some_prev = coverage_spans.sorted_spans_iter.as_mut().unwrap().next();
-        coverage_spans.prev_original_span =
-            coverage_spans.some_prev.as_ref().expect("at least one span").span;
 
         coverage_spans.to_refined_spans()
     }
@@ -317,10 +370,14 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// de-duplicated `CoverageSpan`s.
     fn to_refined_spans(mut self) -> Vec<CoverageSpan> {
         while self.next_coverage_span() {
-            if self.curr().is_mergeable(self.prev()) {
+            if self.some_prev.is_none() {
+                debug!("  initial span");
+                self.check_invoked_macro_name_span();
+            } else if self.curr().is_mergeable(self.prev()) {
                 debug!("  same bcb (and neither is a closure), merge with prev={:?}", self.prev());
                 let prev = self.take_prev();
                 self.curr_mut().merge_from(prev);
+                self.check_invoked_macro_name_span();
             // Note that curr.span may now differ from curr_original_span
             } else if self.prev_ends_before_curr() {
                 debug!(
@@ -329,7 +386,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                     self.prev()
                 );
                 let prev = self.take_prev();
-                self.refined_spans.push(prev);
+                self.push_refined_span(prev);
+                self.check_invoked_macro_name_span();
             } else if self.prev().is_closure {
                 // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
                 // next iter
@@ -344,18 +402,39 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
             } else if self.prev_original_span == self.curr().span {
                 // Note that this compares the new span to `prev_original_span`, which may not
                 // be the full `prev.span` (if merged during the previous iteration).
-                self.hold_pending_dups_unless_dominated();
+                if self.prev().is_macro_expansion() && self.curr().is_macro_expansion() {
+                    // Macros that expand to include branching (such as
+                    // `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
+                    // `trace!()) typically generate callee spans with identical
+                    // ranges (typically the full span of the macro) for all
+                    // `BasicBlocks`. This makes it impossible to distinguish
+                    // the condition (`if val1 != val2`) from the optional
+                    // branched statements (such as the call to `panic!()` on
+                    // assert failure). In this case it is better (or less
+                    // worse) to drop the optional branch bcbs and keep the
+                    // non-conditional statements, to count when reached.
+                    debug!(
+                        "  curr and prev are part of a macro expansion, and curr has the same span \
+                        as prev, but is in a different bcb. Drop curr and keep prev for next iter. \
+                        prev={:?}",
+                        self.prev()
+                    );
+                    self.take_curr();
+                } else {
+                    self.hold_pending_dups_unless_dominated();
+                }
             } else {
                 self.cutoff_prev_at_overlapping_curr();
+                self.check_invoked_macro_name_span();
             }
         }
 
         debug!("    AT END, adding last prev={:?}", self.prev());
         let prev = self.take_prev();
-        let CoverageSpans { pending_dups, mut refined_spans, .. } = self;
+        let pending_dups = self.pending_dups.split_off(0);
         for dup in pending_dups {
             debug!("    ...adding at least one pending dup={:?}", dup);
-            refined_spans.push(dup);
+            self.push_refined_span(dup);
         }
 
         // Async functions wrap a closure that implements the body to be executed. The enclosing
@@ -365,21 +444,60 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
         // excluded. The closure's `Return` is the only one that will be counted. This provides
         // adequate coverage, and more intuitive counts. (Avoids double-counting the closing brace
         // of the function body.)
-        let body_ends_with_closure = if let Some(last_covspan) = refined_spans.last() {
+        let body_ends_with_closure = if let Some(last_covspan) = self.refined_spans.last() {
             last_covspan.is_closure && last_covspan.span.hi() == self.body_span.hi()
         } else {
             false
         };
 
         if !body_ends_with_closure {
-            refined_spans.push(prev);
+            self.push_refined_span(prev);
         }
 
         // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
         // regions for the current function leave room for the closure's own coverage regions
         // (injected separately, from the closure's own MIR).
-        refined_spans.retain(|covspan| !covspan.is_closure);
-        refined_spans
+        self.refined_spans.retain(|covspan| !covspan.is_closure);
+        self.refined_spans
+    }
+
+    fn push_refined_span(&mut self, covspan: CoverageSpan) {
+        let len = self.refined_spans.len();
+        if len > 0 {
+            let last = &mut self.refined_spans[len - 1];
+            if last.is_mergeable(&covspan) {
+                debug!(
+                    "merging new refined span with last refined span, last={:?}, covspan={:?}",
+                    last, covspan
+                );
+                last.merge_from(covspan);
+                return;
+            }
+        }
+        self.refined_spans.push(covspan)
+    }
+
+    fn check_invoked_macro_name_span(&mut self) {
+        if let Some(visible_macro) = self.curr().visible_macro(self.body_span) {
+            if self.prev_expn_span.map_or(true, |prev_expn_span| {
+                self.curr().expn_span.ctxt() != prev_expn_span.ctxt()
+            }) {
+                let merged_prefix_len = self.curr_original_span.lo() - self.curr().span.lo();
+                let after_macro_bang =
+                    merged_prefix_len + BytePos(visible_macro.as_str().bytes().count() as u32 + 1);
+                let mut macro_name_cov = self.curr().clone();
+                self.curr_mut().span =
+                    self.curr().span.with_lo(self.curr().span.lo() + after_macro_bang);
+                macro_name_cov.span =
+                    macro_name_cov.span.with_hi(macro_name_cov.span.lo() + after_macro_bang);
+                debug!(
+                    "  and curr starts a new macro expansion, so add a new span just for \
+                            the macro `{}!`, new span={:?}",
+                    visible_macro, macro_name_cov
+                );
+                self.push_refined_span(macro_name_cov);
+            }
+        }
     }
 
     // Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
@@ -401,14 +519,17 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                     .iter()
                     .enumerate()
                     .filter_map(move |(index, statement)| {
-                        filtered_statement_span(statement, self.body_span).map(|span| {
-                            CoverageSpan::for_statement(statement, span, bcb, bb, index)
-                        })
+                        filtered_statement_span(statement, self.body_span).map(
+                            |(span, expn_span)| {
+                                CoverageSpan::for_statement(
+                                    statement, span, expn_span, bcb, bb, index,
+                                )
+                            },
+                        )
                     })
-                    .chain(
-                        filtered_terminator_span(data.terminator(), self.body_span)
-                            .map(|span| CoverageSpan::for_terminator(span, bcb, bb)),
-                    )
+                    .chain(filtered_terminator_span(data.terminator(), self.body_span).map(
+                        |(span, expn_span)| CoverageSpan::for_terminator(span, expn_span, bcb, bb),
+                    ))
             })
             .collect()
     }
@@ -461,7 +582,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                     let pending_dups = self.pending_dups.split_off(0);
                     for dup in pending_dups.into_iter() {
                         debug!("    ...adding at least one pending={:?}", dup);
-                        self.refined_spans.push(dup);
+                        self.push_refined_span(dup);
                     }
                 } else {
                     self.pending_dups.clear();
@@ -473,12 +594,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order.
     fn next_coverage_span(&mut self) -> bool {
         if let Some(curr) = self.some_curr.take() {
+            self.prev_expn_span = Some(curr.expn_span);
             self.some_prev = Some(curr);
             self.prev_original_span = self.curr_original_span;
         }
         while let Some(curr) = self.sorted_spans_iter.as_mut().unwrap().next() {
             debug!("FOR curr={:?}", curr);
-            if self.prev_starts_after_next(&curr) {
+            if self.some_prev.is_some() && self.prev_starts_after_next(&curr) {
                 debug!(
                     "  prev.span starts after curr.span, so curr will be dropped (skipping past \
                     closure?); prev={:?}",
@@ -535,10 +657,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                 for mut dup in pending_dups.iter().cloned() {
                     dup.span = dup.span.with_hi(left_cutoff);
                     debug!("    ...and at least one pre_closure dup={:?}", dup);
-                    self.refined_spans.push(dup);
+                    self.push_refined_span(dup);
                 }
             }
-            self.refined_spans.push(pre_closure);
+            self.push_refined_span(pre_closure);
         }
         if has_post_closure_span {
             // Update prev.span to start after the closure (and discard curr)
@@ -549,7 +671,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
             }
             self.pending_dups.append(&mut pending_dups);
             let closure_covspan = self.take_curr();
-            self.refined_spans.push(closure_covspan); // since self.prev() was already updated
+            self.push_refined_span(closure_covspan); // since self.prev() was already updated
         } else {
             pending_dups.clear();
         }
@@ -640,7 +762,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
             } else {
                 debug!("  ... adding modified prev={:?}", self.prev());
                 let prev = self.take_prev();
-                self.refined_spans.push(prev);
+                self.push_refined_span(prev);
             }
         } else {
             // with `pending_dups`, `prev` cannot have any statements that don't overlap
@@ -653,10 +775,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     }
 }
 
+/// See `function_source_span()` for a description of the two returned spans.
+/// If the MIR `Statement` is not contributive to computing coverage spans,
+/// returns `None`.
 pub(super) fn filtered_statement_span(
     statement: &'a Statement<'tcx>,
     body_span: Span,
-) -> Option<Span> {
+) -> Option<(Span, Span)> {
     match statement.kind {
         // These statements have spans that are often outside the scope of the executed source code
         // for their parent `BasicBlock`.
@@ -698,10 +823,13 @@ pub(super) fn filtered_statement_span(
     }
 }
 
+/// See `function_source_span()` for a description of the two returned spans.
+/// If the MIR `Terminator` is not contributive to computing coverage spans,
+/// returns `None`.
 pub(super) fn filtered_terminator_span(
     terminator: &'a Terminator<'tcx>,
     body_span: Span,
-) -> Option<Span> {
+) -> Option<(Span, Span)> {
     match terminator.kind {
         // These terminators have spans that don't positively contribute to computing a reasonable
         // span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -741,8 +869,23 @@ pub(super) fn filtered_terminator_span(
     }
 }
 
+/// Returns two spans from the given span (the span associated with a
+/// `Statement` or `Terminator`):
+///
+///   1. An extrapolated span (pre-expansion[^1]) corresponding to a range within
+///      the function's body source. This span is guaranteed to be contained
+///      within, or equal to, the `body_span`. If the extrapolated span is not
+///      contained within the `body_span`, the `body_span` is returned.
+///   2. The actual `span` value from the `Statement`, before expansion.
+///
+/// Only the first span is used when computing coverage code regions. The second
+/// span is useful if additional expansion data is needed (such as to look up
+/// the macro name for a composed span within that macro).)
+///
+/// [^1]Expansions result from Rust syntax including macros, syntactic
+/// sugar, etc.).
 #[inline]
-fn function_source_span(span: Span, body_span: Span) -> Span {
-    let span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
-    if body_span.contains(span) { span } else { body_span }
+fn function_source_span(span: Span, body_span: Span) -> (Span, Span) {
+    let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
+    (if body_span.contains(original_span) { original_span } else { body_span }, span)
 }
diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs
index dee112443d337..9b84173c8a293 100644
--- a/compiler/rustc_mir/src/transform/coverage/tests.rs
+++ b/compiler/rustc_mir/src/transform/coverage/tests.rs
@@ -1,6 +1,10 @@
 //! This crate hosts a selection of "unit tests" for components of the `InstrumentCoverage` MIR
 //! pass.
 //!
+//! ```shell
+//! ./x.py test --keep-stage 1 compiler/rustc_mir --test-args '--show-output coverage'
+//! ```
+//!
 //! The tests construct a few "mock" objects, as needed, to support the `InstrumentCoverage`
 //! functions and algorithms. Mocked objects include instances of `mir::Body`; including
 //! `Terminator`s of various `kind`s, and `Span` objects. Some functions used by or used on
@@ -679,10 +683,15 @@ fn test_make_bcb_counters() {
         let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
         let mut coverage_spans = Vec::new();
         for (bcb, data) in basic_coverage_blocks.iter_enumerated() {
-            if let Some(span) =
+            if let Some((span, expn_span)) =
                 spans::filtered_terminator_span(data.terminator(&mir_body), body_span)
             {
-                coverage_spans.push(spans::CoverageSpan::for_terminator(span, bcb, data.last_bb()));
+                coverage_spans.push(spans::CoverageSpan::for_terminator(
+                    span,
+                    expn_span,
+                    bcb,
+                    data.last_bb(),
+                ));
             }
         }
         let mut coverage_counters = counters::CoverageCounters::new(0);
diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_mir/src/util/spanview.rs
index a9a30e407b4b0..9abfa4a8dc68b 100644
--- a/compiler/rustc_mir/src/util/spanview.rs
+++ b/compiler/rustc_mir/src/util/spanview.rs
@@ -99,7 +99,11 @@ where
     W: Write,
 {
     let def_id = body.source.def_id();
-    let body_span = hir_body(tcx, def_id).value.span;
+    let hir_body = hir_body(tcx, def_id);
+    if hir_body.is_none() {
+        return Ok(());
+    }
+    let body_span = hir_body.unwrap().value.span;
     let mut span_viewables = Vec::new();
     for (bb, data) in body.basic_blocks().iter_enumerated() {
         match spanview {
@@ -664,19 +668,16 @@ fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
     let hir_id =
         tcx.hir().local_def_id_to_hir_id(def_id.as_local().expect("expected DefId is local"));
     let fn_decl_span = tcx.hir().span(hir_id);
-    let body_span = hir_body(tcx, def_id).value.span;
-    if fn_decl_span.ctxt() == body_span.ctxt() {
-        fn_decl_span.to(body_span)
+    if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
+        if fn_decl_span.ctxt() == body_span.ctxt() { fn_decl_span.to(body_span) } else { body_span }
     } else {
-        // This probably occurs for functions defined via macros
-        body_span
+        fn_decl_span
     }
 }
 
-fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx rustc_hir::Body<'tcx> {
+fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<&'tcx rustc_hir::Body<'tcx>> {
     let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
-    let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
-    tcx.hir().body(fn_body_id)
+    hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
 }
 
 fn escape_html(s: &str) -> String {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 52a6e4ff924f4..1f5cb5b8abc8c 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -156,7 +156,7 @@ pub enum InstrumentCoverage {
     Off,
 }
 
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Clone, PartialEq, Hash, Debug)]
 pub enum LinkerPluginLto {
     LinkerPlugin(PathBuf),
     LinkerPluginAuto,
@@ -172,7 +172,7 @@ impl LinkerPluginLto {
     }
 }
 
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Clone, PartialEq, Hash, Debug)]
 pub enum SwitchWithOptPath {
     Enabled(Option<PathBuf>),
     Disabled,
@@ -702,6 +702,7 @@ impl Default for Options {
             cli_forced_codegen_units: None,
             cli_forced_thinlto_off: false,
             remap_path_prefix: Vec::new(),
+            real_rust_source_base_dir: None,
             edition: DEFAULT_EDITION,
             json_artifact_notifications: false,
             json_unused_externs: false,
@@ -778,7 +779,7 @@ pub enum CrateType {
 
 impl_stable_hash_via_hash!(CrateType);
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug, PartialEq, Eq)]
 pub enum Passes {
     Some(Vec<String>),
     All,
@@ -1980,6 +1981,34 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
     }
 
+    // Try to find a directory containing the Rust `src`, for more details see
+    // the doc comment on the `real_rust_source_base_dir` field.
+    let tmp_buf;
+    let sysroot = match &sysroot_opt {
+        Some(s) => s,
+        None => {
+            tmp_buf = crate::filesearch::get_or_default_sysroot();
+            &tmp_buf
+        }
+    };
+    let real_rust_source_base_dir = {
+        // This is the location used by the `rust-src` `rustup` component.
+        let mut candidate = sysroot.join("lib/rustlib/src/rust");
+        if let Ok(metadata) = candidate.symlink_metadata() {
+            // Replace the symlink rustbuild creates, with its destination.
+            // We could try to use `fs::canonicalize` instead, but that might
+            // produce unnecessarily verbose path.
+            if metadata.file_type().is_symlink() {
+                if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
+                    candidate = symlink_dest;
+                }
+            }
+        }
+
+        // Only use this directory if it has a file we can expect to always find.
+        if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
+    };
+
     Options {
         crate_types,
         optimize: opt_level,
@@ -2010,6 +2039,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         cli_forced_codegen_units: codegen_units,
         cli_forced_thinlto_off: disable_thinlto,
         remap_path_prefix,
+        real_rust_source_base_dir,
         edition,
         json_artifact_notifications,
         json_unused_externs,
@@ -2374,6 +2404,7 @@ crate mod dep_tracking {
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
+    impl_dep_tracking_hash_for_sortable_vec_of!((PathBuf, PathBuf));
     impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index fd26f50da5a8e..993b9d6ec78df 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -20,73 +20,112 @@ use std::num::NonZeroUsize;
 use std::path::PathBuf;
 use std::str;
 
-macro_rules! hash_option {
-    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => {{}};
-    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => {{
+macro_rules! insert {
+    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
         if $sub_hashes
             .insert(stringify!($opt_name), $opt_expr as &dyn dep_tracking::DepTrackingHash)
             .is_some()
         {
             panic!("duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
         }
+    };
+}
+
+macro_rules! hash_opt {
+    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [UNTRACKED]) => {{}};
+    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [TRACKED]) => {{ insert!($opt_name, $opt_expr, $sub_hashes) }};
+    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $for_crate_hash: ident, [TRACKED_NO_CRATE_HASH]) => {{
+        if !$for_crate_hash {
+            insert!($opt_name, $opt_expr, $sub_hashes)
+        }
     }};
+    ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, $_for_crate_hash: ident, [SUBSTRUCT]) => {{}};
+}
+
+macro_rules! hash_substruct {
+    ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [UNTRACKED]) => {{}};
+    ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED]) => {{}};
+    ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}};
+    ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => {
+        use crate::config::dep_tracking::DepTrackingHash;
+        $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format);
+    };
 }
 
 macro_rules! top_level_options {
-    (pub struct Options { $(
-        $opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*],
+    ( $( #[$top_level_attr:meta] )* pub struct Options { $(
+        $( #[$attr:meta] )*
+        $opt:ident : $t:ty [$dep_tracking_marker:ident],
     )* } ) => (
         #[derive(Clone)]
+        $( #[$top_level_attr] )*
         pub struct Options {
-            $(pub $opt: $t),*
+            $(
+                $( #[$attr] )*
+                pub $opt: $t
+            ),*
         }
 
         impl Options {
-            pub fn dep_tracking_hash(&self) -> u64 {
+            pub fn dep_tracking_hash(&self, for_crate_hash: bool) -> u64 {
                 let mut sub_hashes = BTreeMap::new();
                 $({
-                    hash_option!($opt,
-                                 &self.$opt,
-                                 &mut sub_hashes,
-                                 [$dep_tracking_marker $($warn_val,
-                                                         $warn_text,
-                                                         self.error_format)*]);
+                    hash_opt!($opt,
+                                &self.$opt,
+                                &mut sub_hashes,
+                                for_crate_hash,
+                                [$dep_tracking_marker]);
                 })*
                 let mut hasher = DefaultHasher::new();
                 dep_tracking::stable_hash(sub_hashes,
                                           &mut hasher,
                                           self.error_format);
+                $({
+                    hash_substruct!($opt,
+                        &self.$opt,
+                        self.error_format,
+                        for_crate_hash,
+                        &mut hasher,
+                        [$dep_tracking_marker]);
+                })*
                 hasher.finish()
             }
         }
     );
 }
 
-// The top-level command-line options struct.
-//
-// For each option, one has to specify how it behaves with regard to the
-// dependency tracking system of incremental compilation. This is done via the
-// square-bracketed directive after the field type. The options are:
-//
-// [TRACKED]
-// A change in the given field will cause the compiler to completely clear the
-// incremental compilation cache before proceeding.
-//
-// [UNTRACKED]
-// Incremental compilation is not influenced by this option.
-//
-// If you add a new option to this struct or one of the sub-structs like
-// `CodegenOptions`, think about how it influences incremental compilation. If in
-// doubt, specify [TRACKED], which is always "correct" but might lead to
-// unnecessary re-compilation.
 top_level_options!(
+    /// The top-level command-line options struct.
+    ///
+    /// For each option, one has to specify how it behaves with regard to the
+    /// dependency tracking system of incremental compilation. This is done via the
+    /// square-bracketed directive after the field type. The options are:
+    ///
+    /// [TRACKED]
+    /// A change in the given field will cause the compiler to completely clear the
+    /// incremental compilation cache before proceeding.
+    ///
+    /// [TRACKED_NO_CRATE_HASH]
+    /// Same as [TRACKED], but will not affect the crate hash. This is useful for options that only
+    /// affect the incremental cache.
+    ///
+    /// [UNTRACKED]
+    /// Incremental compilation is not influenced by this option.
+    ///
+    /// [SUBSTRUCT]
+    /// Second-level sub-structs containing more options.
+    ///
+    /// If you add a new option to this struct or one of the sub-structs like
+    /// `CodegenOptions`, think about how it influences incremental compilation. If in
+    /// doubt, specify [TRACKED], which is always "correct" but might lead to
+    /// unnecessary re-compilation.
     pub struct Options {
-        // The crate config requested for the session, which may be combined
-        // with additional crate configurations during the compile process.
+        /// The crate config requested for the session, which may be combined
+        /// with additional crate configurations during the compile process.
         crate_types: Vec<CrateType> [TRACKED],
         optimize: OptLevel [TRACKED],
-        // Include the `debug_assertions` flag in dependency tracking, since it
-        // can influence whether overflow checks are done or not.
+        /// Include the `debug_assertions` flag in dependency tracking, since it
+        /// can influence whether overflow checks are done or not.
         debug_assertions: bool [TRACKED],
         debuginfo: DebugInfo [TRACKED],
         lint_opts: Vec<(String, lint::Level)> [TRACKED],
@@ -102,52 +141,60 @@ top_level_options!(
         test: bool [TRACKED],
         error_format: ErrorOutputType [UNTRACKED],
 
-        // If `Some`, enable incremental compilation, using the given
-        // directory to store intermediate results.
+        /// If `Some`, enable incremental compilation, using the given
+        /// directory to store intermediate results.
         incremental: Option<PathBuf> [UNTRACKED],
 
-        debugging_opts: DebuggingOptions [TRACKED],
+        debugging_opts: DebuggingOptions [SUBSTRUCT],
         prints: Vec<PrintRequest> [UNTRACKED],
-        // Determines which borrow checker(s) to run. This is the parsed, sanitized
-        // version of `debugging_opts.borrowck`, which is just a plain string.
+        /// Determines which borrow checker(s) to run. This is the parsed, sanitized
+        /// version of `debugging_opts.borrowck`, which is just a plain string.
         borrowck_mode: BorrowckMode [UNTRACKED],
-        cg: CodegenOptions [TRACKED],
+        cg: CodegenOptions [SUBSTRUCT],
         externs: Externs [UNTRACKED],
         extern_dep_specs: ExternDepSpecs [UNTRACKED],
         crate_name: Option<String> [TRACKED],
-        // An optional name to use as the crate for std during std injection,
-        // written `extern crate name as std`. Defaults to `std`. Used by
-        // out-of-tree drivers.
+        /// An optional name to use as the crate for std during std injection,
+        /// written `extern crate name as std`. Defaults to `std`. Used by
+        /// out-of-tree drivers.
         alt_std_name: Option<String> [TRACKED],
-        // Indicates how the compiler should treat unstable features.
+        /// Indicates how the compiler should treat unstable features.
         unstable_features: UnstableFeatures [TRACKED],
 
-        // Indicates whether this run of the compiler is actually rustdoc. This
-        // is currently just a hack and will be removed eventually, so please
-        // try to not rely on this too much.
+        /// Indicates whether this run of the compiler is actually rustdoc. This
+        /// is currently just a hack and will be removed eventually, so please
+        /// try to not rely on this too much.
         actually_rustdoc: bool [TRACKED],
 
-        // Control path trimming.
+        /// Control path trimming.
         trimmed_def_paths: TrimmedDefPaths [TRACKED],
 
-        // Specifications of codegen units / ThinLTO which are forced as a
-        // result of parsing command line options. These are not necessarily
-        // what rustc was invoked with, but massaged a bit to agree with
-        // commands like `--emit llvm-ir` which they're often incompatible with
-        // if we otherwise use the defaults of rustc.
+        /// Specifications of codegen units / ThinLTO which are forced as a
+        /// result of parsing command line options. These are not necessarily
+        /// what rustc was invoked with, but massaged a bit to agree with
+        /// commands like `--emit llvm-ir` which they're often incompatible with
+        /// if we otherwise use the defaults of rustc.
         cli_forced_codegen_units: Option<usize> [UNTRACKED],
         cli_forced_thinlto_off: bool [UNTRACKED],
 
-        // Remap source path prefixes in all output (messages, object files, debug, etc.).
-        remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
+        /// Remap source path prefixes in all output (messages, object files, debug, etc.).
+        remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
+        /// Base directory containing the `src/` for the Rust standard library, and
+        /// potentially `rustc` as well, if we can can find it. Right now it's always
+        /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
+        ///
+        /// This directory is what the virtual `/rustc/$hash` is translated back to,
+        /// if Rust was built with path remapping to `/rustc/$hash` enabled
+        /// (the `rust.remap-debuginfo` option in `config.toml`).
+        real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
 
         edition: Edition [TRACKED],
 
-        // `true` if we're emitting JSON blobs about each artifact produced
-        // by the compiler.
+        /// `true` if we're emitting JSON blobs about each artifact produced
+        /// by the compiler.
         json_artifact_notifications: bool [TRACKED],
 
-        // `true` if we're emitting a JSON blob containing the unused externs
+        /// `true` if we're emitting a JSON blob containing the unused externs
         json_unused_externs: bool [UNTRACKED],
 
         pretty: Option<PpMode> [UNTRACKED],
@@ -166,10 +213,10 @@ macro_rules! options {
     ($struct_name:ident, $setter_name:ident, $defaultfn:ident,
      $buildfn:ident, $prefix:expr, $outputname:expr,
      $stat:ident, $mod_desc:ident, $mod_set:ident,
-     $($opt:ident : $t:ty = (
+     $($( #[$attr:meta] )* $opt:ident : $t:ty = (
         $init:expr,
         $parse:ident,
-        [$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*],
+        [$dep_tracking_marker:ident],
         $desc:expr)
      ),* ,) =>
 (
@@ -177,7 +224,7 @@ macro_rules! options {
     pub struct $struct_name { $(pub $opt: $t),* }
 
     pub fn $defaultfn() -> $struct_name {
-        $struct_name { $($opt: $init),* }
+        $struct_name { $( $( #[$attr] )* $opt: $init),* }
     }
 
     pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
@@ -219,18 +266,21 @@ macro_rules! options {
         return op;
     }
 
-    impl dep_tracking::DepTrackingHash for $struct_name {
-        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+    impl $struct_name {
+        fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 {
             let mut sub_hashes = BTreeMap::new();
             $({
-                hash_option!($opt,
-                             &self.$opt,
-                             &mut sub_hashes,
-                             [$dep_tracking_marker $($dep_warn_val,
-                                                     $dep_warn_text,
-                                                     error_format)*]);
+                hash_opt!($opt,
+                            &self.$opt,
+                            &mut sub_hashes,
+                            _for_crate_hash,
+                            [$dep_tracking_marker]);
             })*
-            dep_tracking::stable_hash(sub_hashes, hasher, error_format);
+            let mut hasher = DefaultHasher::new();
+            dep_tracking::stable_hash(sub_hashes,
+                                        &mut hasher,
+                                        error_format);
+            hasher.finish()
         }
     }
 
@@ -1128,7 +1178,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
         "run the self profiler and output the raw event data"),
-    // keep this in sync with the event filter names in librustc_data_structures/profiling.rs
+    /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs
     self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
         "specify the events recorded by the self profiler;
         for example: `-Z self-profile-events=default,query-keys`
@@ -1140,7 +1190,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "show spans for compiler debugging (expr|pat|ty)"),
     span_debug: bool = (false, parse_bool, [UNTRACKED],
         "forward proc_macro::Span's `Debug` impl to `Span`"),
-    // o/w tests have closure@path
+    /// o/w tests have closure@path
     span_free_formats: bool = (false, parse_bool, [UNTRACKED],
         "exclude spans when debug-printing compiler state (default: no)"),
     src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
@@ -1161,10 +1211,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "select processor to schedule for (`rustc --print target-cpus` for details)"),
     thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "enable ThinLTO when possible"),
-    // We default to 1 here since we want to behave like
-    // a sequential compiler for now. This'll likely be adjusted
-    // in the future. Note that -Zthreads=0 is the way to get
-    // the num_cpus behavior.
+    /// We default to 1 here since we want to behave like
+    /// a sequential compiler for now. This'll likely be adjusted
+    /// in the future. Note that -Zthreads=0 is the way to get
+    /// the num_cpus behavior.
     threads: usize = (1, parse_threads, [UNTRACKED],
         "use a thread pool with N threads"),
     time: bool = (false, parse_bool, [UNTRACKED],
@@ -1220,7 +1270,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     // - compiler/rustc_interface/src/tests.rs
 }
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, PartialEq, Eq, Debug)]
 pub enum WasiExecModel {
     Command,
     Reactor,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 7bff634fb2dd0..e7dfc4b8c4128 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -214,15 +214,6 @@ pub struct Session {
     /// drown everything else in noise.
     miri_unleashed_features: Lock<Vec<(Span, Option<Symbol>)>>,
 
-    /// Base directory containing the `src/` for the Rust standard library, and
-    /// potentially `rustc` as well, if we can can find it. Right now it's always
-    /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
-    ///
-    /// This directory is what the virtual `/rustc/$hash` is translated back to,
-    /// if Rust was built with path remapping to `/rustc/$hash` enabled
-    /// (the `rust.remap-debuginfo` option in `config.toml`).
-    pub real_rust_source_base_dir: Option<PathBuf>,
-
     /// Architecture to use for interpreting asm!.
     pub asm_arch: Option<InlineAsmArch>,
 
@@ -1390,26 +1381,6 @@ pub fn build_session(
         _ => CtfeBacktrace::Disabled,
     });
 
-    // Try to find a directory containing the Rust `src`, for more details see
-    // the doc comment on the `real_rust_source_base_dir` field.
-    let real_rust_source_base_dir = {
-        // This is the location used by the `rust-src` `rustup` component.
-        let mut candidate = sysroot.join("lib/rustlib/src/rust");
-        if let Ok(metadata) = candidate.symlink_metadata() {
-            // Replace the symlink rustbuild creates, with its destination.
-            // We could try to use `fs::canonicalize` instead, but that might
-            // produce unnecessarily verbose path.
-            if metadata.file_type().is_symlink() {
-                if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
-                    candidate = symlink_dest;
-                }
-            }
-        }
-
-        // Only use this directory if it has a file we can expect to always find.
-        if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
-    };
-
     let asm_arch =
         if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None };
 
@@ -1453,7 +1424,6 @@ pub fn build_session(
         system_library_path: OneThread::new(RefCell::new(Default::default())),
         ctfe_backtrace,
         miri_unleashed_features: Lock::new(Default::default()),
-        real_rust_source_base_dir,
         asm_arch,
         target_features: FxHashSet::default(),
         known_attrs: Lock::new(MarkedAttrs::new()),
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index e7c9edea7653a..dd51574efca0a 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -83,10 +83,8 @@ def_regs! {
         x13: reg = ["x13", "w13"],
         x14: reg = ["x14", "w14"],
         x15: reg = ["x15", "w15"],
-        x16: reg = ["x16", "w16"],
         x17: reg = ["x17", "w17"],
         x18: reg = ["x18", "w18"],
-        x19: reg = ["x19", "w19"],
         x20: reg = ["x20", "w20"],
         x21: reg = ["x21", "w21"],
         x22: reg = ["x22", "w22"],
@@ -96,7 +94,7 @@ def_regs! {
         x26: reg = ["x26", "w26"],
         x27: reg = ["x27", "w27"],
         x28: reg = ["x28", "w28"],
-        x30: reg = ["x30", "w30", "lr"],
+        x30: reg = ["x30", "w30", "lr", "wlr"],
         v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0"],
         v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1"],
         v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2"],
@@ -129,7 +127,11 @@ def_regs! {
         v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29"],
         v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30"],
         v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31"],
-        #error = ["x29", "fp"] =>
+        #error = ["x16", "w16"] =>
+            "x16 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["x19", "w19"] =>
+            "x19 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["x29", "w29", "fp", "wfp"] =>
             "the frame pointer cannot be used as an operand for inline asm",
         #error = ["sp", "wsp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index a7a708fe7dec3..4c323fc35d643 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -98,7 +98,6 @@ def_regs! {
         r5: reg, reg_thumb = ["r5", "v2"],
         r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7,
         r8: reg = ["r8", "v5"],
-        r9: reg = ["r9", "v6", "rfp"],
         r10: reg = ["r10", "sl"],
         r11: reg = ["r11", "fp"] % frame_pointer_r11,
         r12: reg = ["r12", "ip"],
@@ -185,6 +184,8 @@ def_regs! {
         q15: qreg = ["q15"],
         #error = ["r6", "v3"] =>
             "r6 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["r9", "v6", "rfp"] =>
+            "r9 is used internally by LLVM and cannot be used as an operand for inline asm",
         #error = ["r13", "sp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["r15", "pc"] =>
diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs
index d41941d0b4cd7..74afddb69dc75 100644
--- a/compiler/rustc_target/src/asm/hexagon.rs
+++ b/compiler/rustc_target/src/asm/hexagon.rs
@@ -60,7 +60,6 @@ def_regs! {
         r16: reg = ["r16"],
         r17: reg = ["r17"],
         r18: reg = ["r18"],
-        r19: reg = ["r19"],
         r20: reg = ["r20"],
         r21: reg = ["r21"],
         r22: reg = ["r22"],
@@ -70,6 +69,8 @@ def_regs! {
         r26: reg = ["r26"],
         r27: reg = ["r27"],
         r28: reg = ["r28"],
+        #error = ["r19"] =>
+            "r19 is used internally by LLVM and cannot be used as an operand for inline asm",
         #error = ["r29", "sp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["r30", "fr"] =>
diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs
index 185d6ac8246c9..e276a9175f9ab 100644
--- a/compiler/rustc_target/src/asm/riscv.rs
+++ b/compiler/rustc_target/src/asm/riscv.rs
@@ -66,7 +66,6 @@ def_regs! {
         x5: reg = ["x5", "t0"],
         x6: reg = ["x6", "t1"],
         x7: reg = ["x7", "t2"],
-        x9: reg = ["x9", "s1"],
         x10: reg = ["x10", "a0"],
         x11: reg = ["x11", "a1"],
         x12: reg = ["x12", "a2"],
@@ -121,6 +120,8 @@ def_regs! {
         f29: freg = ["f29", "ft9"],
         f30: freg = ["f30", "ft10"],
         f31: freg = ["f31", "ft11"],
+        #error = ["x9", "s1"] =>
+            "s1 is used internally by LLVM and cannot be used as an operand for inline asm",
         #error = ["x8", "s0", "fp"] =>
             "the frame pointer cannot be used as an operand for inline asm",
         #error = ["x2", "sp"] =>
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index 90660dad4c2a1..48f83ca7cd49a 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -152,13 +152,41 @@ fn high_byte(
     }
 }
 
+fn rbx_reserved(
+    arch: InlineAsmArch,
+    _has_feature: impl FnMut(&str) -> bool,
+    _target: &Target,
+) -> Result<(), &'static str> {
+    match arch {
+        InlineAsmArch::X86 => Ok(()),
+        InlineAsmArch::X86_64 => {
+            Err("rbx is used internally by LLVM and cannot be used as an operand for inline asm")
+        }
+        _ => unreachable!(),
+    }
+}
+
+fn esi_reserved(
+    arch: InlineAsmArch,
+    _has_feature: impl FnMut(&str) -> bool,
+    _target: &Target,
+) -> Result<(), &'static str> {
+    match arch {
+        InlineAsmArch::X86 => {
+            Err("esi is used internally by LLVM and cannot be used as an operand for inline asm")
+        }
+        InlineAsmArch::X86_64 => Ok(()),
+        _ => unreachable!(),
+    }
+}
+
 def_regs! {
     X86 X86InlineAsmReg X86InlineAsmRegClass {
         ax: reg, reg_abcd = ["ax", "eax", "rax"],
-        bx: reg, reg_abcd = ["bx", "ebx", "rbx"],
+        bx: reg, reg_abcd = ["bx", "ebx", "rbx"] % rbx_reserved,
         cx: reg, reg_abcd = ["cx", "ecx", "rcx"],
         dx: reg, reg_abcd = ["dx", "edx", "rdx"],
-        si: reg = ["si", "esi", "rsi"],
+        si: reg = ["si", "esi", "rsi"] % esi_reserved,
         di: reg = ["di", "edi", "rdi"],
         r8: reg = ["r8", "r8w", "r8d"] % x86_64_only,
         r9: reg = ["r9", "r9w", "r9d"] % x86_64_only,
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 38901a35296e1..62a3a87eeb850 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1627,6 +1627,11 @@ impl Cargo {
     pub fn add_rustc_lib_path(&mut self, builder: &Builder<'_>, compiler: Compiler) {
         builder.add_rustc_lib_path(compiler, &mut self.command);
     }
+
+    pub fn current_dir(&mut self, dir: &Path) -> &mut Cargo {
+        self.command.current_dir(dir);
+        self
+    }
 }
 
 impl From<Cargo> for Command {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b9d7ecf8c0eb1..965d11621450b 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -632,6 +632,26 @@ impl Step for Clippy {
 
         cargo.add_rustc_lib_path(builder, compiler);
 
+        if builder.try_run(&mut cargo.into()) {
+            // The tests succeeded; nothing to do.
+            return;
+        }
+
+        if !builder.config.cmd.bless() {
+            std::process::exit(1);
+        }
+
+        let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run");
+        cargo.arg("-p").arg("clippy_dev");
+        // clippy_dev gets confused if it can't find `clippy/Cargo.toml`
+        cargo.current_dir(&builder.src.join("src").join("tools").join("clippy"));
+        if builder.config.rust_optimize {
+            cargo.env("PROFILE", "release");
+        } else {
+            cargo.env("PROFILE", "debug");
+        }
+        cargo.arg("--");
+        cargo.arg("bless");
         builder.run(&mut cargo.into());
     }
 }
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index 4f9033cedc3ff..7c2bf62185530 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -535,20 +535,20 @@ Here is the list of currently supported register classes:
 
 | Architecture | Register class | Registers | LLVM constraint code |
 | ------------ | -------------- | --------- | -------------------- |
-| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `r[8-15]` (x86-64 only) | `r` |
+| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `bp`, `r[8-15]` (x86-64 only) | `r` |
 | x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` |
 | x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` |
-| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `r[8-15]b` | `q` |
+| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `bpl`, `r[8-15]b` | `q` |
 | x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` |
 | x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |
 | x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |
 | x86 | `kreg` | `k[1-7]` | `Yk` |
-| AArch64 | `reg` | `x[0-28]`, `x30` | `r` |
+| AArch64 | `reg` | `x[0-30]` | `r` |
 | AArch64 | `vreg` | `v[0-31]` | `w` |
 | AArch64 | `vreg_low16` | `v[0-15]` | `x` |
-| ARM | `reg` | `r[0-5]` `r7`\*, `r[8-10]`, `r11`\*, `r12`, `r14` | `r` |
+| ARM | `reg` | `r[0-12]`, `r14` | `r` |
 | ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |
-| ARM (ARM) | `reg_thumb` | `r[0-r10]`, `r12`, `r14` | `l` |
+| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
 | ARM | `sreg` | `s[0-31]` | `t` |
 | ARM | `sreg_low16` | `s[0-15]` | `x` |
 | ARM | `dreg` | `d[0-31]` | `w` |
@@ -573,9 +573,7 @@ Here is the list of currently supported register classes:
 >
 > Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
 >
-> Note #4: On ARM the frame pointer is either `r7` or `r11` depending on the platform.
->
-> Note #5: WebAssembly doesn't have registers, so named registers are not supported.
+> Note #4: WebAssembly doesn't have registers, so named registers are not supported.
 
 Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
 
@@ -677,13 +675,15 @@ Some registers cannot be used for input or output operands:
 | All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
 | All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon), `$fp` (MIPS) | The frame pointer cannot be used as an input or output. |
 | ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. |
-| ARM | `r6` | `r6` is used internally by LLVM as a base pointer and therefore cannot be used as an input or output. |
+| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `r19` (Hexagon), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
 | x86 | `k0` | This is a constant zero register which can't be modified. |
 | x86 | `ip` | This is the program counter, not a real register. |
 | x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). |
 | x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). |
 | AArch64 | `xzr` | This is a constant zero register which can't be modified. |
+| AArch64 | `x16` | This is used internally by LLVM for speculative load hardening. |
 | ARM | `pc` | This is the program counter, not a real register. |
+| ARM | `r9` | This is a reserved register on some ARM targets. |
 | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
 | MIPS | `$1` or `$at` | Reserved for assembler. |
 | MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
@@ -693,9 +693,10 @@ Some registers cannot be used for input or output operands:
 | RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
 | Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
 
-In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are:
-- The frame pointer on all architectures.
-- `r6` on ARM.
+In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are the frame pointer and base pointer
+- The frame pointer and LLVM base pointer on all architectures.
+- `x16` on AArch64.
+- `r6` and `r9` on ARM.
 
 ## Template modifiers
 
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index a024fa49b0e8b..1c5c9fe2e1c91 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -117,9 +117,12 @@ h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
 }
 h1.fqn {
 	display: flex;
-	width: 100%;
 	border-bottom: 1px dashed;
 	margin-top: 0;
+
+	/* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
+	   above the h1 */
+	padding-left: 1px;
 }
 h1.fqn > .in-band > a:hover {
 	text-decoration: underline;
@@ -385,13 +388,6 @@ nav.sub {
 	position: relative;
 }
 
-#results {
-	position: absolute;
-	right: 0;
-	left: 0;
-	overflow: auto;
-}
-
 #results > table {
 	width: 100%;
 	table-layout: fixed;
@@ -453,20 +449,14 @@ nav.sub {
 }
 
 .content .out-of-band {
-	float: right;
+	flex-grow: 0;
+	text-align: right;
 	font-size: 23px;
 	margin: 0px;
-	padding: 0px;
+	padding: 0 0 0 12px;
 	font-weight: normal;
 }
 
-h1.fqn > .out-of-band {
-	float: unset;
-	flex: 1;
-	text-align: right;
-	margin-left: 8px;
-}
-
 h3.impl > .out-of-band {
 	font-size: 21px;
 }
@@ -486,6 +476,7 @@ h4 > code, h3 > code, .invisible > code {
 }
 
 .content .in-band {
+	flex-grow: 1;
 	margin: 0px;
 	padding: 0px;
 }
@@ -1484,10 +1475,6 @@ h4 > .notable-traits {
 		display: none !important;
 	}
 
-	h1.fqn {
-		overflow: initial;
-	}
-
 	.theme-picker {
 		left: 10px;
 		top: 54px;
diff --git a/src/llvm-project b/src/llvm-project
index 0ed6038a318e3..06c2b9d1e23b7 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 0ed6038a318e34e3d76a9e55bdebc4cfd17f902a
+Subproject commit 06c2b9d1e23b73ffb5059769542097b86d5a4623
diff --git a/src/test/codegen/asm-multiple-options.rs b/src/test/codegen/asm-multiple-options.rs
index c702742bf1a63..baf9f3e9bd14d 100644
--- a/src/test/codegen/asm-multiple-options.rs
+++ b/src/test/codegen/asm-multiple-options.rs
@@ -10,7 +10,7 @@
 #[no_mangle]
 pub unsafe fn pure(x: i32) {
     let y: i32;
-    asm!("", out("ax") y, in("bx") x, options(pure), options(nomem));
+    asm!("", out("ax") y, in("cx") x, options(pure), options(nomem));
 }
 
 pub static mut VAR: i32 = 0;
diff --git a/src/test/codegen/asm-options.rs b/src/test/codegen/asm-options.rs
index 21e7eb4379634..70391661b0cfb 100644
--- a/src/test/codegen/asm-options.rs
+++ b/src/test/codegen/asm-options.rs
@@ -10,7 +10,7 @@
 #[no_mangle]
 pub unsafe fn pure(x: i32) {
     let y: i32;
-    asm!("", out("ax") y, in("bx") x, options(pure, nomem));
+    asm!("", out("ax") y, in("cx") x, options(pure, nomem));
 }
 
 // CHECK-LABEL: @noreturn
diff --git a/src/test/incremental/commandline-args.rs b/src/test/incremental/commandline-args.rs
index 08a0232f661f7..35b7183db7fac 100644
--- a/src/test/incremental/commandline-args.rs
+++ b/src/test/incremental/commandline-args.rs
@@ -2,20 +2,23 @@
 // the cache while changing an untracked one doesn't.
 
 // ignore-asmjs wasm2js does not support source maps yet
-// revisions:rpass1 rpass2 rpass3
+// revisions:rpass1 rpass2 rpass3 rpass4
 // compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
 #![rustc_partition_codegened(module="commandline_args", cfg="rpass2")]
 #![rustc_partition_reused(module="commandline_args", cfg="rpass3")]
+#![rustc_partition_codegened(module="commandline_args", cfg="rpass4")]
 
 // Between revisions 1 and 2, we are changing the debuginfo-level, which should
 // invalidate the cache. Between revisions 2 and 3, we are adding `--verbose`
-// which should have no effect on the cache:
+// which should have no effect on the cache. Between revisions, we are adding
+// `--remap-path-prefix` which should invalidate the cache:
 //[rpass1] compile-flags: -C debuginfo=0
 //[rpass2] compile-flags: -C debuginfo=2
 //[rpass3] compile-flags: -C debuginfo=2 --verbose
+//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
 
 pub fn main() {
     // empty
diff --git a/src/test/pretty/asm.pp b/src/test/pretty/asm.pp
index c86d8a1197188..a2065039692b7 100644
--- a/src/test/pretty/asm.pp
+++ b/src/test/pretty/asm.pp
@@ -21,7 +21,7 @@
         asm!("{0}", out(reg) a);
         asm!("{0}", inout(reg) b);
         asm!("{0} {1}", out(reg) _, inlateout(reg) b => _);
-        asm!("", out("al") _, lateout("rbx") _);
+        asm!("", out("al") _, lateout("rcx") _);
         asm!("inst1\ninst2");
         asm!("inst1 {0}, 42\ninst2 {1}, 24", in(reg) a, out(reg) b);
         asm!("inst2 {1}, 24\ninst1 {0}, 42", in(reg) a, out(reg) b);
diff --git a/src/test/pretty/asm.rs b/src/test/pretty/asm.rs
index 33f25e5216b4e..1156ab769a043 100644
--- a/src/test/pretty/asm.rs
+++ b/src/test/pretty/asm.rs
@@ -15,7 +15,7 @@ pub fn main() {
         asm!("{0}", out(reg) a);
         asm!("{name}", name = inout(reg) b);
         asm!("{} {}", out(reg) _, inlateout(reg) b => _);
-        asm!("", out("al") _, lateout("rbx") _);
+        asm!("", out("al") _, lateout("rcx") _);
         asm!("inst1", "inst2");
         asm!("inst1 {}, 42", "inst2 {}, 24", in(reg) a, out(reg) b);
         asm!("inst2 {1}, 24", "inst1 {0}, 42", in(reg) a, out(reg) b);
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inner_items.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inner_items.txt
index f5b5184044f65..883254a09ba7d 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inner_items.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inner_items.txt
@@ -1,9 +1,9 @@
     1|       |#![allow(unused_assignments, unused_variables, dead_code)]
     2|       |
     3|      1|fn main() {
-    4|       |    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|       |    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|       |    // dependent conditions.
+    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    6|      1|    // dependent conditions.
     7|      1|    let is_true = std::env::args().len() == 1;
     8|      1|
     9|      1|    let mut countdown = 0;
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt
new file mode 100644
index 0000000000000..8256daa1419b3
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -0,0 +1,196 @@
+    1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+    2|       |
+    3|       |// expect-exit-status-101
+    4|     21|#[derive(PartialEq, Eq)]
+                                  ^0
+  ------------------
+  | <issue_84561::Foo as core::cmp::PartialEq>::eq:
+  |    4|     21|#[derive(PartialEq, Eq)]
+  ------------------
+  | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
+  ------------------
+    5|       |struct Foo(u32);
+    6|      1|fn test3() {
+    7|      1|    let is_true = std::env::args().len() == 1;
+    8|      1|    let bar = Foo(1);
+    9|      1|    assert_eq!(bar, Foo(1));
+   10|      1|    let baz = Foo(0);
+   11|      1|    assert_ne!(baz, Foo(1));
+   12|      1|    println!("{:?}", Foo(1));
+   13|      1|    println!("{:?}", bar);
+   14|      1|    println!("{:?}", baz);
+   15|      1|
+   16|      1|    assert_eq!(Foo(1), Foo(1));
+   17|      1|    assert_ne!(Foo(0), Foo(1));
+   18|      1|    assert_eq!(Foo(2), Foo(2));
+   19|      1|    let bar = Foo(0);
+   20|      1|    assert_ne!(bar, Foo(3));
+   21|      1|    assert_ne!(Foo(0), Foo(4));
+   22|      1|    assert_eq!(Foo(3), Foo(3), "with a message");
+                                             ^0
+   23|      1|    println!("{:?}", bar);
+   24|      1|    println!("{:?}", Foo(1));
+   25|      1|
+   26|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+                                             ^0                 ^0                      ^0
+   27|      1|    assert_ne!(
+   28|       |        Foo(0)
+   29|       |        ,
+   30|       |        Foo(5)
+   31|       |        ,
+   32|      0|        "{}"
+   33|      0|        ,
+   34|      0|        if
+   35|      0|        is_true
+   36|       |        {
+   37|      0|            "true message"
+   38|       |        } else {
+   39|      0|            "false message"
+   40|       |        }
+   41|       |    );
+   42|       |
+   43|      1|    let is_true = std::env::args().len() == 1;
+   44|      1|
+   45|      1|    assert_eq!(
+   46|      1|        Foo(1),
+   47|      1|        Foo(1)
+   48|      1|    );
+   49|      1|    assert_ne!(
+   50|      1|        Foo(0),
+   51|      1|        Foo(1)
+   52|      1|    );
+   53|      1|    assert_eq!(
+   54|      1|        Foo(2),
+   55|      1|        Foo(2)
+   56|      1|    );
+   57|      1|    let bar = Foo(1);
+   58|      1|    assert_ne!(
+   59|      1|        bar,
+   60|      1|        Foo(3)
+   61|      1|    );
+   62|      1|    if is_true {
+   63|      1|        assert_ne!(
+   64|      1|            Foo(0),
+   65|      1|            Foo(4)
+   66|      1|        );
+   67|       |    } else {
+   68|      0|        assert_eq!(
+   69|      0|            Foo(3),
+   70|      0|            Foo(3)
+   71|      0|        );
+   72|       |    }
+   73|      1|    if is_true {
+   74|      1|        assert_ne!(
+   75|       |            Foo(0),
+   76|       |            Foo(4),
+   77|      0|            "with a message"
+   78|       |        );
+   79|       |    } else {
+   80|      0|        assert_eq!(
+   81|       |            Foo(3),
+   82|       |            Foo(3),
+   83|      0|            "with a message"
+   84|       |        );
+   85|       |    }
+   86|      1|    assert_ne!(
+   87|      1|        if is_true {
+   88|      1|            Foo(0)
+   89|       |        } else {
+   90|      0|            Foo(1)
+   91|       |        },
+   92|       |        Foo(5)
+   93|       |    );
+   94|      1|    assert_ne!(
+   95|      1|        Foo(5),
+   96|      1|        if is_true {
+   97|      1|            Foo(0)
+   98|       |        } else {
+   99|      0|            Foo(1)
+  100|       |        }
+  101|       |    );
+  102|      1|    assert_ne!(
+  103|      1|        if is_true {
+  104|      1|            assert_eq!(
+  105|      1|                Foo(3),
+  106|      1|                Foo(3)
+  107|      1|            );
+  108|      1|            Foo(0)
+  109|       |        } else {
+  110|      0|            assert_ne!(
+  111|      0|                if is_true {
+  112|      0|                    Foo(0)
+  113|       |                } else {
+  114|      0|                    Foo(1)
+  115|       |                },
+  116|       |                Foo(5)
+  117|       |            );
+  118|      0|            Foo(1)
+  119|       |        },
+  120|       |        Foo(5),
+  121|      0|        "with a message"
+  122|       |    );
+  123|      1|    assert_eq!(
+  124|       |        Foo(1),
+  125|       |        Foo(3),
+  126|      1|        "this assert should fail"
+  127|       |    );
+  128|      0|    assert_eq!(
+  129|       |        Foo(3),
+  130|       |        Foo(3),
+  131|      0|        "this assert should not be reached"
+  132|       |    );
+  133|      0|}
+  134|       |
+  135|       |impl std::fmt::Debug for Foo {
+  136|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+  137|      7|        write!(f, "try and succeed")?;
+                                                  ^0
+  138|      7|        Ok(())
+  139|      7|    }
+  140|       |}
+  141|       |
+  142|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
+  143|       |
+  144|       |macro_rules! debug {
+  145|       |    ($($arg:tt)+) => (
+  146|       |        if unsafe { DEBUG_LEVEL_ENABLED } {
+  147|       |            println!($($arg)+);
+  148|       |        }
+  149|       |    );
+  150|       |}
+  151|       |
+  152|      1|fn test1() {
+  153|      1|    debug!("debug is enabled");
+                         ^0
+  154|      1|    debug!("debug is enabled");
+                         ^0
+  155|      1|    let _ = 0;
+  156|      1|    debug!("debug is enabled");
+                         ^0
+  157|      1|    unsafe {
+  158|      1|        DEBUG_LEVEL_ENABLED = true;
+  159|      1|    }
+  160|      1|    debug!("debug is enabled");
+  161|      1|}
+  162|       |
+  163|       |macro_rules! call_debug {
+  164|       |    ($($arg:tt)+) => (
+  165|      1|        fn call_print(s: &str) {
+  166|      1|            print!("{}", s);
+  167|      1|        }
+  168|       |
+  169|       |        call_print("called from call_debug: ");
+  170|       |        debug!($($arg)+);
+  171|       |    );
+  172|       |}
+  173|       |
+  174|      1|fn test2() {
+  175|      1|    call_debug!("debug is enabled");
+  176|      1|}
+  177|       |
+  178|      1|fn main() {
+  179|      1|    test1();
+  180|      1|    test2();
+  181|      1|    test3();
+  182|      1|}
+
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
index f5beb9ef24a0e..c2d5143a61816 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt
@@ -3,9 +3,9 @@
     3|       |use std::fmt::Debug;
     4|       |
     5|      1|pub fn used_function() {
-    6|       |    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    7|       |    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    8|       |    // dependent conditions.
+    6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    7|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+    8|      1|    // dependent conditions.
     9|      1|    let is_true = std::env::args().len() == 1;
    10|      1|    let mut countdown = 0;
    11|      1|    if is_true {
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
index cc98956e3073a..dab31cbf4ac9e 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
@@ -5,9 +5,9 @@
     5|       |use std::fmt::Debug;
     6|       |
     7|      1|pub fn used_function() {
-    8|       |    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    9|       |    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   10|       |    // dependent conditions.
+    8|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+    9|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   10|      1|    // dependent conditions.
    11|      1|    let is_true = std::env::args().len() == 1;
    12|      1|    let mut countdown = 0;
    13|      1|    if is_true {
@@ -19,9 +19,9 @@
    18|       |
    19|       |#[inline(always)]
    20|      1|pub fn used_inline_function() {
-   21|       |    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-   22|       |    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   23|       |    // dependent conditions.
+   21|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   22|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   23|      1|    // dependent conditions.
    24|      1|    let is_true = std::env::args().len() == 1;
    25|      1|    let mut countdown = 0;
    26|      1|    if is_true {
diff --git a/src/test/run-make-fulldeps/coverage/issue-84561.rs b/src/test/run-make-fulldeps/coverage/issue-84561.rs
new file mode 100644
index 0000000000000..b39a289c45e20
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/issue-84561.rs
@@ -0,0 +1,182 @@
+// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+
+// expect-exit-status-101
+#[derive(PartialEq, Eq)]
+struct Foo(u32);
+fn test3() {
+    let is_true = std::env::args().len() == 1;
+    let bar = Foo(1);
+    assert_eq!(bar, Foo(1));
+    let baz = Foo(0);
+    assert_ne!(baz, Foo(1));
+    println!("{:?}", Foo(1));
+    println!("{:?}", bar);
+    println!("{:?}", baz);
+
+    assert_eq!(Foo(1), Foo(1));
+    assert_ne!(Foo(0), Foo(1));
+    assert_eq!(Foo(2), Foo(2));
+    let bar = Foo(0);
+    assert_ne!(bar, Foo(3));
+    assert_ne!(Foo(0), Foo(4));
+    assert_eq!(Foo(3), Foo(3), "with a message");
+    println!("{:?}", bar);
+    println!("{:?}", Foo(1));
+
+    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+    assert_ne!(
+        Foo(0)
+        ,
+        Foo(5)
+        ,
+        "{}"
+        ,
+        if
+        is_true
+        {
+            "true message"
+        } else {
+            "false message"
+        }
+    );
+
+    let is_true = std::env::args().len() == 1;
+
+    assert_eq!(
+        Foo(1),
+        Foo(1)
+    );
+    assert_ne!(
+        Foo(0),
+        Foo(1)
+    );
+    assert_eq!(
+        Foo(2),
+        Foo(2)
+    );
+    let bar = Foo(1);
+    assert_ne!(
+        bar,
+        Foo(3)
+    );
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4)
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3)
+        );
+    }
+    if is_true {
+        assert_ne!(
+            Foo(0),
+            Foo(4),
+            "with a message"
+        );
+    } else {
+        assert_eq!(
+            Foo(3),
+            Foo(3),
+            "with a message"
+        );
+    }
+    assert_ne!(
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        },
+        Foo(5)
+    );
+    assert_ne!(
+        Foo(5),
+        if is_true {
+            Foo(0)
+        } else {
+            Foo(1)
+        }
+    );
+    assert_ne!(
+        if is_true {
+            assert_eq!(
+                Foo(3),
+                Foo(3)
+            );
+            Foo(0)
+        } else {
+            assert_ne!(
+                if is_true {
+                    Foo(0)
+                } else {
+                    Foo(1)
+                },
+                Foo(5)
+            );
+            Foo(1)
+        },
+        Foo(5),
+        "with a message"
+    );
+    assert_eq!(
+        Foo(1),
+        Foo(3),
+        "this assert should fail"
+    );
+    assert_eq!(
+        Foo(3),
+        Foo(3),
+        "this assert should not be reached"
+    );
+}
+
+impl std::fmt::Debug for Foo {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(f, "try and succeed")?;
+        Ok(())
+    }
+}
+
+static mut DEBUG_LEVEL_ENABLED: bool = false;
+
+macro_rules! debug {
+    ($($arg:tt)+) => (
+        if unsafe { DEBUG_LEVEL_ENABLED } {
+            println!($($arg)+);
+        }
+    );
+}
+
+fn test1() {
+    debug!("debug is enabled");
+    debug!("debug is enabled");
+    let _ = 0;
+    debug!("debug is enabled");
+    unsafe {
+        DEBUG_LEVEL_ENABLED = true;
+    }
+    debug!("debug is enabled");
+}
+
+macro_rules! call_debug {
+    ($($arg:tt)+) => (
+        fn call_print(s: &str) {
+            print!("{}", s);
+        }
+
+        call_print("called from call_debug: ");
+        debug!($($arg)+);
+    );
+}
+
+fn test2() {
+    call_debug!("debug is enabled");
+}
+
+fn main() {
+    test1();
+    test2();
+    test3();
+}
diff --git a/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile
index 50ff3dd56ce92..371f94715a8c1 100644
--- a/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile
+++ b/src/test/run-make-fulldeps/incr-add-rust-src-component/Makefile
@@ -1,7 +1,7 @@
 -include ../tools.mk
 
 # rust-lang/rust#70924: Test that if we add rust-src component in between two
-# incremetnal compiles, the compiler does not ICE on the second.
+# incremental compiles, the compiler does not ICE on the second.
 
 # This test uses `ln -s` rather than copying to save testing time, but its
 # usage doesn't work on windows. So ignore windows.
diff --git a/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs
new file mode 100644
index 0000000000000..c496a3556c84e
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-83737-erasing-bound-vars.rs
@@ -0,0 +1,14 @@
+// build-pass
+// compile-flags: --edition 2018
+// compile-flags: --crate-type rlib
+
+use std::future::Future;
+
+async fn handle<F>(slf: &F)
+where
+    F: Fn(&()) -> Box<dyn for<'a> Future<Output = ()> + Unpin>,
+{
+    (slf)(&()).await;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-84604.rs b/src/test/ui/lifetimes/issue-84604.rs
new file mode 100644
index 0000000000000..df8368da0a09a
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-84604.rs
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags: -Zsymbol-mangling-version=v0
+
+pub fn f<T: ?Sized>() {}
+pub trait Frob<T: ?Sized> {}
+fn main() {
+    f::<dyn Frob<str>>();
+    f::<dyn for<'a> Frob<str>>();
+}
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index d951ca0e6308d..4676c2affad79 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -44,7 +44,7 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str
     create_test(&lint).context("Unable to create a test for the new lint")
 }
 
-fn create_lint(lint: &LintData) -> io::Result<()> {
+fn create_lint(lint: &LintData<'_>) -> io::Result<()> {
     let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass {
         "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"),
         "late" => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"),
@@ -68,7 +68,7 @@ fn create_lint(lint: &LintData) -> io::Result<()> {
     write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())
 }
 
-fn create_test(lint: &LintData) -> io::Result<()> {
+fn create_test(lint: &LintData<'_>) -> io::Result<()> {
     fn create_project_layout<P: Into<PathBuf>>(lint_name: &str, location: P, case: &str, hint: &str) -> io::Result<()> {
         let mut path = location.into().join(case);
         fs::create_dir(&path)?;
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index f4d354f0bf942..e1110721f6ece 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -83,14 +83,7 @@ fn default_config() -> compiletest::Config {
         third_party_crates(),
     ));
 
-    config.build_base = if cargo::is_rustc_test_suite() {
-        // This make the stderr files go to clippy OUT_DIR on rustc repo build dir
-        let mut path = PathBuf::from(env!("OUT_DIR"));
-        path.push("test_build_base");
-        path
-    } else {
-        host_lib().join("test_build_base")
-    };
+    config.build_base = host_lib().join("test_build_base");
     config.rustc_path = clippy_driver_path();
     config
 }