about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs4
-rw-r--r--compiler/rustc_ast/src/token.rs27
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs73
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/coverageinfo/map.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs2
-rw-r--r--compiler/rustc_expand/src/base.rs40
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs3
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs46
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/mod.rs25
-rw-r--r--compiler/rustc_mir/src/transform/coverage/query.rs41
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs9
-rw-r--r--compiler/rustc_parse/src/parser/item.rs44
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs4
-rw-r--r--compiler/rustc_session/src/config.rs19
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs1
-rw-r--r--library/alloc/benches/lib.rs1
-rw-r--r--library/alloc/benches/vec.rs89
-rw-r--r--library/alloc/src/collections/btree/map.rs7
-rw-r--r--library/alloc/src/vec/mod.rs95
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/vec.rs126
-rw-r--r--library/core/src/hash/mod.rs10
-rw-r--r--library/std/src/collections/hash/map.rs3
-rw-r--r--library/std/src/collections/hash/set.rs3
-rw-r--r--library/std/src/sys/unix/stack_overflow.rs5
-rw-r--r--library/std/src/sys/unix/thread.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile10
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh14
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/Makefile6
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt2
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt53
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/Makefile8
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html161
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html79
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html82
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html94
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html183
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html113
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html173
-rw-r--r--src/test/run-make-fulldeps/coverage/async.rs2
-rw-r--r--src/test/run-make-fulldeps/coverage/inline.rs51
-rw-r--r--src/test/ui/asm/inline-syntax.arm.stderr14
-rw-r--r--src/test/ui/asm/inline-syntax.rs38
-rw-r--r--src/test/ui/asm/inline-syntax.x86_64.stderr50
-rw-r--r--src/test/ui/lint/register-tool-lint.rs11
-rw-r--r--src/test/ui/lint/register-tool-lint.stderr27
-rw-r--r--src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs21
-rw-r--r--src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr2
-rw-r--r--src/test/ui/parser/duplicate-visibility.rs5
-rw-r--r--src/test/ui/parser/duplicate-visibility.stderr25
-rw-r--r--src/test/ui/parser/issue-76437-async.rs7
-rw-r--r--src/test/ui/parser/issue-76437-async.stderr11
-rw-r--r--src/test/ui/parser/issue-76437-const-async-unsafe.rs7
-rw-r--r--src/test/ui/parser/issue-76437-const-async-unsafe.stderr11
-rw-r--r--src/test/ui/parser/issue-76437-const-async.rs7
-rw-r--r--src/test/ui/parser/issue-76437-const-async.stderr11
-rw-r--r--src/test/ui/parser/issue-76437-const.rs7
-rw-r--r--src/test/ui/parser/issue-76437-const.stderr11
-rw-r--r--src/test/ui/parser/issue-76437-pub-crate-unsafe.rs7
-rw-r--r--src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr11
-rw-r--r--src/test/ui/parser/issue-76437-unsafe.rs7
-rw-r--r--src/test/ui/parser/issue-76437-unsafe.stderr11
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs13
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr25
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout22
-rw-r--r--src/test/ui/tool_lints.rs6
-rw-r--r--src/test/ui/tool_lints.stderr12
-rw-r--r--src/test/ui/unknown-lint-tool-name.rs12
-rw-r--r--src/test/ui/unknown-lint-tool-name.stderr24
-rw-r--r--src/tools/compiletest/src/main.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs9
79 files changed, 1997 insertions, 218 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 40b0cefd83a..2c5e180f80d 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -33,10 +33,6 @@ impl MarkedAttrs {
     }
 }
 
-pub fn is_known_lint_tool(m_item: Ident) -> bool {
-    [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item.name)
-}
-
 impl NestedMetaItem {
     /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
     pub fn meta_item(&self) -> Option<&MetaItem> {
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 093f7f2668c..7e58426d27d 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -784,33 +784,6 @@ impl Nonterminal {
             NtTT(tt) => tt.span(),
         }
     }
-
-    /// This nonterminal looks like some specific enums from
-    /// `proc-macro-hack` and `procedural-masquerade` crates.
-    /// We need to maintain some special pretty-printing behavior for them due to incorrect
-    /// asserts in old versions of those crates and their wide use in the ecosystem.
-    /// See issue #73345 for more details.
-    /// FIXME(#73933): Remove this eventually.
-    pub fn pretty_printing_compatibility_hack(&self) -> bool {
-        let item = match self {
-            NtItem(item) => item,
-            NtStmt(stmt) => match &stmt.kind {
-                ast::StmtKind::Item(item) => item,
-                _ => return false,
-            },
-            _ => return false,
-        };
-
-        let name = item.ident.name;
-        if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
-            if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
-                if let [variant] = &*enum_def.variants {
-                    return variant.ident.name == sym::Input;
-                }
-            }
-        }
-        false
-    }
 }
 
 impl PartialEq for Nonterminal {
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 36cd6c281b4..8d8b3f4f6aa 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -7,7 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_parse::parser::Parser;
 use rustc_parse_format as parse;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::{
+    symbol::{kw, sym, Symbol},
+    BytePos,
+};
 use rustc_span::{InnerSpan, Span};
 
 struct AsmArgs {
@@ -399,6 +402,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
     let mut line_spans = Vec::with_capacity(args.templates.len());
     let mut curarg = 0;
 
+    let default_dialect = ecx.sess.inline_asm_dialect();
+
     for template_expr in args.templates.into_iter() {
         if !template.is_empty() {
             template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
@@ -424,6 +429,60 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
 
         let template_str = &template_str.as_str();
         let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
+
+        if let Some(snippet) = &template_snippet {
+            let snippet = snippet.trim_matches('"');
+            match default_dialect {
+                ast::LlvmAsmDialect::Intel => {
+                    if let Some(span) = check_syntax_directive(snippet, ".intel_syntax") {
+                        let span = template_span.from_inner(span);
+                        let mut err = ecx.struct_span_err(span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues");
+                        err.span_suggestion(
+                            span,
+                            "remove this assembler directive",
+                            "".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                        err.emit();
+                    }
+
+                    if let Some(span) = check_syntax_directive(snippet, ".att_syntax") {
+                        let span = template_span.from_inner(span);
+                        let mut err = ecx.struct_span_err(span, "using the .att_syntax directive may cause issues, use the att_syntax option instead");
+                        let asm_end = sp.hi() - BytePos(2);
+                        let suggestions = vec![
+                            (span, "".to_string()),
+                            (
+                                Span::new(asm_end, asm_end, sp.ctxt()),
+                                ", options(att_syntax)".to_string(),
+                            ),
+                        ];
+                        err.multipart_suggestion(
+                        "remove the assembler directive and replace it with options(att_syntax)",
+                        suggestions,
+                        Applicability::MachineApplicable,
+                    );
+                        err.emit();
+                    }
+                }
+                ast::LlvmAsmDialect::Att => {
+                    if let Some(span) = check_syntax_directive(snippet, ".att_syntax") {
+                        let span = template_span.from_inner(span);
+                        let mut err = ecx.struct_span_err(span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues");
+                        err.span_suggestion(
+                            span,
+                            "remove this assembler directive",
+                            "".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                        err.emit();
+                    }
+
+                    // Use of .intel_syntax is ignored
+                }
+            }
+        }
+
         let mut parser = parse::Parser::new(
             template_str,
             str_style,
@@ -631,3 +690,15 @@ pub fn expand_asm<'cx>(
         }
     }
 }
+
+fn check_syntax_directive<S: AsRef<str>>(piece: S, syntax: &str) -> Option<InnerSpan> {
+    let piece = piece.as_ref();
+    if let Some(idx) = piece.find(syntax) {
+        let end =
+            idx + &piece[idx..].find(|c| matches!(c, '\n' | ';')).unwrap_or(piece[idx..].len());
+        // Offset by one because these represent the span with the " removed
+        Some(InnerSpan::new(idx + 1, end + 1))
+    } else {
+        None
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 444a9d4ba04..352638aa88e 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -254,7 +254,7 @@ fn save_function_record(
 ///
 /// 1. The file name of an "Unreachable" function must match the file name of the existing
 ///    codegenned (covered) function to which the unreachable code regions will be added.
-/// 2. The function to which the unreachable code regions will be added must not be a genaric
+/// 2. The function to which the unreachable code regions will be added must not be a generic
 ///    function (must not have type parameters) because the coverage tools will get confused
 ///    if the codegenned function has more than one instantiation and additional `CodeRegion`s
 ///    attached to only one of those instantiations.
@@ -284,7 +284,7 @@ fn add_unreachable_coverage<'tcx>(
     let all_def_ids: DefIdSet =
         tcx.mir_keys(LOCAL_CRATE).iter().map(|local_def_id| local_def_id.to_def_id()).collect();
 
-    let (codegenned_def_ids, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+    let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE);
 
     let mut unreachable_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default();
     for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) {
diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
index 549b8d41f51..af6482fdbc2 100644
--- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
+++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
@@ -8,7 +8,7 @@ use rustc_middle::mir::coverage::{
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::TyCtxt;
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Expression {
     lhs: ExpressionOperandId,
     op: Op,
@@ -64,7 +64,9 @@ impl<'tcx> FunctionCoverage<'tcx> {
 
     /// Adds a code region to be counted by an injected counter intrinsic.
     pub fn add_counter(&mut self, id: CounterValueReference, region: CodeRegion) {
-        self.counters[id].replace(region).expect_none("add_counter called with duplicate `id`");
+        if let Some(previous_region) = self.counters[id].replace(region.clone()) {
+            assert_eq!(previous_region, region, "add_counter: code region for id changed");
+        }
     }
 
     /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
@@ -94,9 +96,18 @@ impl<'tcx> FunctionCoverage<'tcx> {
             expression_id, lhs, op, rhs, region
         );
         let expression_index = self.expression_index(u32::from(expression_id));
-        self.expressions[expression_index]
-            .replace(Expression { lhs, op, rhs, region })
-            .expect_none("add_counter_expression called with duplicate `id_descending_from_max`");
+        if let Some(previous_expression) = self.expressions[expression_index].replace(Expression {
+            lhs,
+            op,
+            rhs,
+            region: region.clone(),
+        }) {
+            assert_eq!(
+                previous_expression,
+                Expression { lhs, op, rhs, region },
+                "add_counter_expression: expression for id changed"
+            );
+        }
     }
 
     /// Add a region that will be marked as "unreachable", with a constant "zero counter".
diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
index a115d358666..5ab1baafb57 100644
--- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
@@ -2,27 +2,38 @@ use crate::traits::*;
 
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::Coverage;
+use rustc_middle::mir::SourceScope;
 
 use super::FunctionCx;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
-    pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage) {
+    pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
+        // Determine the instance that coverage data was originally generated for.
+        let scope_data = &self.mir.source_scopes[scope];
+        let instance = if let Some((inlined_instance, _)) = scope_data.inlined {
+            self.monomorphize(inlined_instance)
+        } else if let Some(inlined_scope) = scope_data.inlined_parent_scope {
+            self.monomorphize(self.mir.source_scopes[inlined_scope].inlined.unwrap().0)
+        } else {
+            self.instance
+        };
+
         let Coverage { kind, code_region } = coverage;
         match kind {
             CoverageKind::Counter { function_source_hash, id } => {
-                if bx.set_function_source_hash(self.instance, function_source_hash) {
+                if bx.set_function_source_hash(instance, function_source_hash) {
                     // If `set_function_source_hash()` returned true, the coverage map is enabled,
                     // so continue adding the counter.
                     if let Some(code_region) = code_region {
                         // Note: Some counters do not have code regions, but may still be referenced
                         // from expressions. In that case, don't add the counter to the coverage map,
                         // but do inject the counter intrinsic.
-                        bx.add_coverage_counter(self.instance, id, code_region);
+                        bx.add_coverage_counter(instance, id, code_region);
                     }
 
-                    let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id());
+                    let coverageinfo = bx.tcx().coverageinfo(instance.def_id());
 
-                    let fn_name = bx.create_pgo_func_name_var(self.instance);
+                    let fn_name = bx.create_pgo_func_name_var(instance);
                     let hash = bx.const_u64(function_source_hash);
                     let num_counters = bx.const_u32(coverageinfo.num_counters);
                     let index = bx.const_u32(u32::from(id));
@@ -34,11 +45,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             CoverageKind::Expression { id, lhs, op, rhs } => {
-                bx.add_coverage_counter_expression(self.instance, id, lhs, op, rhs, code_region);
+                bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
             }
             CoverageKind::Unreachable => {
                 bx.add_coverage_unreachable(
-                    self.instance,
+                    instance,
                     code_region.expect("unreachable regions always have code regions"),
                 );
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 5523e5f2e86..fe7f6288adb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -112,7 +112,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx
             }
             mir::StatementKind::Coverage(box ref coverage) => {
-                self.codegen_coverage(&mut bx, coverage.clone());
+                self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
                 bx
             }
             mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 05e5c13dab7..594b9a82ad0 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -10,6 +10,8 @@ use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagnosticBuilder, ErrorReported};
+use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
+use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
 use rustc_span::def_id::DefId;
@@ -1241,3 +1243,41 @@ pub fn get_exprs_from_tts(
     }
     Some(es)
 }
+
+/// This nonterminal looks like some specific enums from
+/// `proc-macro-hack` and `procedural-masquerade` crates.
+/// We need to maintain some special pretty-printing behavior for them due to incorrect
+/// asserts in old versions of those crates and their wide use in the ecosystem.
+/// See issue #73345 for more details.
+/// FIXME(#73933): Remove this eventually.
+pub(crate) fn pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
+    let item = match nt {
+        Nonterminal::NtItem(item) => item,
+        Nonterminal::NtStmt(stmt) => match &stmt.kind {
+            ast::StmtKind::Item(item) => item,
+            _ => return false,
+        },
+        _ => return false,
+    };
+
+    let name = item.ident.name;
+    if name == sym::ProceduralMasqueradeDummyType {
+        if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
+            if let [variant] = &*enum_def.variants {
+                if variant.ident.name == sym::Input {
+                    sess.buffer_lint_with_diagnostic(
+                        &PROC_MACRO_BACK_COMPAT,
+                        item.ident.span,
+                        ast::CRATE_NODE_ID,
+                        "using `procedural-masquerade` crate",
+                        BuiltinLintDiagnostics::ProcMacroBackCompat(
+                        "The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. \
+                        Versions of this crate below 0.1.7 will eventually stop compiling.".to_string())
+                    );
+                    return true;
+                }
+            }
+        }
+    }
+    false
+}
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 8cbaa7c945a..61b776ff2d2 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -90,7 +90,8 @@ impl MultiItemModifier for ProcMacroDerive {
             }
             _ => unreachable!(),
         };
-        let input = if item.pretty_printing_compatibility_hack() {
+        let input = if crate::base::pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess)
+        {
             TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
         } else {
             nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes)
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 837fad90580..67edfe19da3 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -187,7 +187,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
                         delimiter: Delimiter::None,
                         stream,
                         span: DelimSpan::from_single(span),
-                        flatten: nt.pretty_printing_compatibility_hack(),
+                        flatten: crate::base::pretty_printing_compatibility_hack(&nt, sess),
                     })
                 }
             }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 3ba687124ae..c9de85a2f18 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -748,7 +748,7 @@ impl<'a> EarlyContext<'a> {
             sess,
             krate,
             lint_store,
-            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store),
+            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs),
             buffered,
         }
     }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5e6b090027c..a332c300787 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,13 +1,12 @@
 use crate::context::{CheckLintNameResult, LintStore};
 use crate::late::unerased_lint_store;
 use rustc_ast as ast;
-use rustc_ast::attr;
 use rustc_ast::unwrap_or;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::LevelAndSource;
@@ -32,7 +31,8 @@ use std::cmp;
 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
     let store = unerased_lint_store(tcx);
-    let levels = LintLevelsBuilder::new(tcx.sess, false, &store);
+    let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX });
+    let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs);
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
@@ -56,6 +56,7 @@ pub struct LintLevelsBuilder<'s> {
     cur: u32,
     warn_about_weird_lints: bool,
     store: &'s LintStore,
+    crate_attrs: &'s [ast::Attribute],
 }
 
 pub struct BuilderPush {
@@ -64,7 +65,12 @@ pub struct BuilderPush {
 }
 
 impl<'s> LintLevelsBuilder<'s> {
-    pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore) -> Self {
+    pub fn new(
+        sess: &'s Session,
+        warn_about_weird_lints: bool,
+        store: &'s LintStore,
+        crate_attrs: &'s [ast::Attribute],
+    ) -> Self {
         let mut builder = LintLevelsBuilder {
             sess,
             sets: LintLevelSets::new(),
@@ -72,6 +78,7 @@ impl<'s> LintLevelsBuilder<'s> {
             id_to_set: Default::default(),
             warn_about_weird_lints,
             store,
+            crate_attrs,
         };
         builder.process_command_line(sess, store);
         assert_eq!(builder.sets.list.len(), 1);
@@ -304,15 +311,22 @@ impl<'s> LintLevelsBuilder<'s> {
                 };
                 let tool_name = if meta_item.path.segments.len() > 1 {
                     let tool_ident = meta_item.path.segments[0].ident;
-                    if !attr::is_known_lint_tool(tool_ident) {
-                        struct_span_err!(
+                    if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
+                        let mut err = struct_span_err!(
                             sess,
                             tool_ident.span,
                             E0710,
-                            "an unknown tool name found in scoped lint: `{}`",
+                            "unknown tool name `{}` found in scoped lint: `{}`",
+                            tool_ident.name,
                             pprust::path_to_string(&meta_item.path),
-                        )
-                        .emit();
+                        );
+                        if sess.is_nightly_build() {
+                            err.help(&format!(
+                                "add `#![register_tool({})]` to the crate root",
+                                tool_ident.name
+                            ));
+                        }
+                        err.emit();
                         continue;
                     }
 
@@ -559,6 +573,20 @@ impl<'s> LintLevelsBuilder<'s> {
     }
 }
 
+fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
+    if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) {
+        return true;
+    }
+    // Look for registered tools
+    // NOTE: does no error handling; error handling is done by rustc_resolve.
+    sess.filter_by_name(attrs, sym::register_tool)
+        .filter_map(|attr| attr.meta_item_list())
+        .flat_map(std::convert::identity)
+        .filter_map(|nested_meta| nested_meta.ident())
+        .map(|ident| ident.name)
+        .any(|name| name == m_item)
+}
+
 struct LintLevelMapBuilder<'a, 'tcx> {
     levels: LintLevelsBuilder<'tcx>,
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 872cf1ed194..ae367db019b 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1407,6 +1407,14 @@ rustc_queries! {
     query is_codegened_item(def_id: DefId) -> bool {
         desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) }
     }
+
+    /// All items participating in code generation together with items inlined into them.
+    query codegened_and_inlined_items(_: CrateNum)
+        -> &'tcx DefIdSet {
+        eval_always
+       desc { "codegened_and_inlined_items" }
+    }
+
     query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
         desc { "codegen_unit" }
     }
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
index b68a8104fba..dc2379fd92b 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
@@ -424,8 +424,33 @@ fn collect_and_partition_mono_items<'tcx>(
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
+fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx DefIdSet {
+    let (items, cgus) = tcx.collect_and_partition_mono_items(cnum);
+    let mut visited = DefIdSet::default();
+    let mut result = items.clone();
+
+    for cgu in cgus {
+        for (item, _) in cgu.items() {
+            if let MonoItem::Fn(ref instance) = item {
+                let did = instance.def_id();
+                if !visited.insert(did) {
+                    continue;
+                }
+                for scope in &tcx.instance_mir(instance.def).source_scopes {
+                    if let Some((ref inlined, _)) = scope.inlined {
+                        result.insert(inlined.def_id());
+                    }
+                }
+            }
+        }
+    }
+
+    tcx.arena.alloc(result)
+}
+
 pub fn provide(providers: &mut Providers) {
     providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
+    providers.codegened_and_inlined_items = codegened_and_inlined_items;
 
     providers.is_codegened_item = |tcx, def_id| {
         let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs
index 4b455a6a1ba..de8447f1974 100644
--- a/compiler/rustc_mir/src/transform/coverage/query.rs
+++ b/compiler/rustc_mir/src/transform/coverage/query.rs
@@ -1,8 +1,7 @@
 use super::*;
 
 use rustc_middle::mir::coverage::*;
-use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{self, Coverage, CoverageInfo, Location};
+use rustc_middle::mir::{self, Body, Coverage, CoverageInfo};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
@@ -85,10 +84,21 @@ impl CoverageVisitor {
             }
         }
     }
-}
 
-impl Visitor<'_> for CoverageVisitor {
-    fn visit_coverage(&mut self, coverage: &Coverage, _location: Location) {
+    fn visit_body(&mut self, body: &Body<'_>) {
+        for bb_data in body.basic_blocks().iter() {
+            for statement in bb_data.statements.iter() {
+                if let StatementKind::Coverage(box ref coverage) = statement.kind {
+                    if is_inlined(body, statement) {
+                        continue;
+                    }
+                    self.visit_coverage(coverage);
+                }
+            }
+        }
+    }
+
+    fn visit_coverage(&mut self, coverage: &Coverage) {
         if self.add_missing_operands {
             match coverage.kind {
                 CoverageKind::Expression { lhs, rhs, .. } => {
@@ -129,10 +139,14 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo
 }
 
 fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
-    for bb_data in mir_body(tcx, def_id).basic_blocks().iter() {
+    let body = mir_body(tcx, def_id);
+    for bb_data in body.basic_blocks().iter() {
         for statement in bb_data.statements.iter() {
             if let StatementKind::Coverage(box ref coverage) = statement.kind {
                 if let Some(code_region) = coverage.code_region.as_ref() {
+                    if is_inlined(body, statement) {
+                        continue;
+                    }
                     return Some(code_region.file_name);
                 }
             }
@@ -151,13 +165,17 @@ fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
 }
 
 fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
-    mir_body(tcx, def_id)
-        .basic_blocks()
+    let body = mir_body(tcx, def_id);
+    body.basic_blocks()
         .iter()
         .map(|data| {
             data.statements.iter().filter_map(|statement| match statement.kind {
                 StatementKind::Coverage(box ref coverage) => {
-                    coverage.code_region.as_ref() // may be None
+                    if is_inlined(body, statement) {
+                        None
+                    } else {
+                        coverage.code_region.as_ref() // may be None
+                    }
                 }
                 _ => None,
             })
@@ -165,3 +183,8 @@ fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx Cod
         .flatten()
         .collect()
 }
+
+fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
+    let scope_data = &body.source_scopes[statement.source_info.scope];
+    scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some()
+}
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index dd06daecd5d..12fdbd6582e 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -39,15 +39,6 @@ struct CallSite<'tcx> {
 
 /// Returns true if MIR inlining is enabled in the current compilation session.
 crate fn is_enabled(tcx: TyCtxt<'_>) -> bool {
-    if tcx.sess.opts.debugging_opts.instrument_coverage {
-        // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
-        // counters can be invalidated, such as by merging coverage counter statements from
-        // a pre-inlined function into a different function. This kind of change is invalid,
-        // so inlining must be skipped. Note: This check is performed here so inlining can
-        // be disabled without preventing other optimizations (regardless of `mir_opt_level`).
-        return false;
-    }
-
     if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir {
         return enabled;
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 025415036b6..70dbaa53d38 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -204,6 +204,7 @@ impl<'a> Parser<'a> {
         def: &mut Defaultness,
         req_name: ReqName,
     ) -> PResult<'a, Option<ItemInfo>> {
+        let def_final = def == &Defaultness::Final;
         let mut def = || mem::replace(def, Defaultness::Final);
 
         let info = if self.eat_keyword(kw::Use) {
@@ -226,7 +227,7 @@ impl<'a> Parser<'a> {
             }
 
             (Ident::invalid(), ItemKind::Use(tree))
-        } else if self.check_fn_front_matter() {
+        } else if self.check_fn_front_matter(def_final) {
             // FUNCTION ITEM
             let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
             (ident, ItemKind::Fn(box FnKind(def(), sig, generics, body)))
@@ -1634,18 +1635,27 @@ impl<'a> Parser<'a> {
     }
 
     /// Is the current token the start of an `FnHeader` / not a valid parse?
-    pub(super) fn check_fn_front_matter(&mut self) -> bool {
+    ///
+    /// `check_pub` adds additional `pub` to the checks in case users place it
+    /// wrongly, can be used to ensure `pub` never comes after `default`.
+    pub(super) fn check_fn_front_matter(&mut self, check_pub: bool) -> bool {
         // We use an over-approximation here.
         // `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
-        const QUALS: [Symbol; 4] = [kw::Const, kw::Async, kw::Unsafe, kw::Extern];
+        // `pub` is added in case users got confused with the ordering like `async pub fn`,
+        // only if it wasn't preceeded by `default` as `default pub` is invalid.
+        let quals: &[Symbol] = if check_pub {
+            &[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+        } else {
+            &[kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+        };
         self.check_keyword(kw::Fn) // Definitely an `fn`.
             // `$qual fn` or `$qual $qual`:
-            || QUALS.iter().any(|&kw| self.check_keyword(kw))
+            || quals.iter().any(|&kw| self.check_keyword(kw))
                 && self.look_ahead(1, |t| {
                     // `$qual fn`, e.g. `const fn` or `async fn`.
                     t.is_keyword(kw::Fn)
                     // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`.
-                    || t.is_non_raw_ident_where(|i| QUALS.contains(&i.name)
+                    || t.is_non_raw_ident_where(|i| quals.contains(&i.name)
                         // Rule out 2015 `const async: T = val`.
                         && i.is_reserved()
                         // Rule out unsafe extern block.
@@ -1666,6 +1676,7 @@ impl<'a> Parser<'a> {
     /// FnFrontMatter = FnQual "fn" ;
     /// ```
     pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
+        let sp_start = self.token.span;
         let constness = self.parse_constness();
         let asyncness = self.parse_asyncness();
         let unsafety = self.parse_unsafety();
@@ -1679,8 +1690,27 @@ impl<'a> Parser<'a> {
             // It is possible for `expect_one_of` to recover given the contents of
             // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
             // account for this.
-            if !self.expect_one_of(&[], &[])? {
-                unreachable!()
+            match self.expect_one_of(&[], &[]) {
+                Ok(true) => {}
+                Ok(false) => unreachable!(),
+                Err(mut err) => {
+                    // Recover incorrect visibility order such as `async pub`.
+                    if self.check_keyword(kw::Pub) {
+                        let sp = sp_start.to(self.prev_token.span);
+                        if let Ok(snippet) = self.span_to_snippet(sp) {
+                            let vis = self.parse_visibility(FollowedByType::No)?;
+                            let vs = pprust::vis_to_string(&vis);
+                            let vs = vs.trim_end();
+                            err.span_suggestion(
+                                sp_start.to(self.prev_token.span),
+                                &format!("visibility `{}` must come before `{}`", vs, snippet),
+                                format!("{} {}", vs, snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                    return Err(err);
+                }
             }
         }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 8f03bfd4c3a..0f7b8ebd376 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -209,7 +209,7 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(kw::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
-        } else if self.check_fn_front_matter() {
+        } else if self.check_fn_front_matter(false) {
             // Function pointer type
             self.parse_ty_bare_fn(lo, Vec::new(), recover_return_sign)?
         } else if self.check_keyword(kw::For) {
@@ -217,7 +217,7 @@ impl<'a> Parser<'a> {
             //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
             //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
             let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-            if self.check_fn_front_matter() {
+            if self.check_fn_front_matter(false) {
                 self.parse_ty_bare_fn(lo, lifetime_defs, recover_return_sign)?
             } else {
                 let path = self.parse_path(PathStyle::Type)?;
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c1be90efc72..75078a12311 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1937,25 +1937,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
             }
             Some(SymbolManglingVersion::V0) => {}
         }
-
-        if let Some(mir_opt_level) = debugging_opts.mir_opt_level {
-            if mir_opt_level > 1 {
-                // Functions inlined during MIR transform can, at best, make it impossible to
-                // effectively cover inlined functions, and, at worst, break coverage map generation
-                // during LLVM codegen. For example, function counter IDs are only unique within a
-                // function. Inlining after these counters are injected can produce duplicate counters,
-                // resulting in an invalid coverage map (and ICE); so this option combination is not
-                // allowed.
-                early_warn(
-                    error_format,
-                    &format!(
-                        "`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
-                    is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
-                        mir_opt_level,
-                    ),
-                );
-            }
-        }
     }
 
     if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4f611118360..fc57b6b8ace 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -793,6 +793,13 @@ impl Session {
         }
     }
 
+    pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect {
+        match self.asm_arch {
+            Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel,
+            _ => rustc_ast::LlvmAsmDialect::Att,
+        }
+    }
+
     pub fn relocation_model(&self) -> RelocModel {
         self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
     }
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
index 33a785fdfee..aa823b13fdd 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             linker: Some("rust-lld".to_string()),
+            llvm_abiname: "lp64d".to_string(),
             cpu: "generic-rv64".to_string(),
             max_atomic_width: Some(64),
             atomic_cas: true,
diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs
index 32edb86d101..38a8f65f169 100644
--- a/library/alloc/benches/lib.rs
+++ b/library/alloc/benches/lib.rs
@@ -4,6 +4,7 @@
 #![feature(btree_drain_filter)]
 #![feature(map_first_last)]
 #![feature(repr_simd)]
+#![feature(slice_partition_dedup)]
 #![feature(test)]
 
 extern crate test;
diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index 89893b6209c..73eb353f6e7 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -671,3 +671,92 @@ fn bench_map_fast(b: &mut Bencher) {
     let data = black_box([(0, 0); LEN]);
     b.iter(|| map_fast(&data));
 }
+
+fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) {
+    let mask = if buf.len() < 8192 {
+        0xFF
+    } else if buf.len() < 200_000 {
+        0xFFFF
+    } else {
+        0xFFFF_FFFF
+    };
+
+    for item in buf.iter_mut() {
+        seed ^= seed << 13;
+        seed ^= seed >> 17;
+        seed ^= seed << 5;
+
+        *item = seed & mask;
+    }
+
+    buf.sort();
+}
+
+fn bench_vec_dedup_old(b: &mut Bencher, sz: usize) {
+    let mut template = vec![0u32; sz];
+    b.bytes = std::mem::size_of_val(template.as_slice()) as u64;
+    random_sorted_fill(0x43, &mut template);
+
+    let mut vec = template.clone();
+    b.iter(|| {
+        let len = {
+            let (dedup, _) = vec.partition_dedup();
+            dedup.len()
+        };
+        vec.truncate(len);
+
+        black_box(vec.first());
+        vec.clear();
+        vec.extend_from_slice(&template);
+    });
+}
+
+fn bench_vec_dedup_new(b: &mut Bencher, sz: usize) {
+    let mut template = vec![0u32; sz];
+    b.bytes = std::mem::size_of_val(template.as_slice()) as u64;
+    random_sorted_fill(0x43, &mut template);
+
+    let mut vec = template.clone();
+    b.iter(|| {
+        vec.dedup();
+        black_box(vec.first());
+        vec.clear();
+        vec.extend_from_slice(&template);
+    });
+}
+
+#[bench]
+fn bench_dedup_old_100(b: &mut Bencher) {
+    bench_vec_dedup_old(b, 100);
+}
+#[bench]
+fn bench_dedup_new_100(b: &mut Bencher) {
+    bench_vec_dedup_new(b, 100);
+}
+
+#[bench]
+fn bench_dedup_old_1000(b: &mut Bencher) {
+    bench_vec_dedup_old(b, 1000);
+}
+#[bench]
+fn bench_dedup_new_1000(b: &mut Bencher) {
+    bench_vec_dedup_new(b, 1000);
+}
+
+#[bench]
+fn bench_dedup_old_10000(b: &mut Bencher) {
+    bench_vec_dedup_old(b, 10000);
+}
+#[bench]
+fn bench_dedup_new_10000(b: &mut Bencher) {
+    bench_vec_dedup_new(b, 10000);
+}
+
+#[bench]
+fn bench_dedup_old_100000(b: &mut Bencher) {
+    bench_vec_dedup_old(b, 100000);
+}
+#[bench]
+fn bench_dedup_new_100000(b: &mut Bencher) {
+    bench_vec_dedup_new(b, 100000);
+}
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 622983996aa..a0dbb289252 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -21,15 +21,15 @@ use Entry::*;
 /// We might temporarily have fewer elements during methods.
 pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 
-// A tree in a `BTreeMap` is a tree in the `node` module with addtional invariants:
+// A tree in a `BTreeMap` is a tree in the `node` module with additional invariants:
 // - Keys must appear in ascending order (according to the key's type).
 // - If the root node is internal, it must contain at least 1 element.
 // - Every non-root node contains at least MIN_LEN elements.
 //
-// An empty map may be represented both by the absense of a root node or by a
+// An empty map may be represented both by the absence of a root node or by a
 // root node that is an empty leaf.
 
-/// A map based on a B-Tree.
+/// A map based on a [B-Tree].
 ///
 /// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
 /// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
@@ -63,6 +63,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
 /// non-termination.
 ///
+/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
 /// [`Cell`]: core::cell::Cell
 /// [`RefCell`]: core::cell::RefCell
 ///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 9731a8e1d1d..135279874bb 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1512,15 +1512,98 @@ impl<T, A: Allocator> Vec<T, A> {
     /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
     /// ```
     #[stable(feature = "dedup_by", since = "1.16.0")]
-    pub fn dedup_by<F>(&mut self, same_bucket: F)
+    pub fn dedup_by<F>(&mut self, mut same_bucket: F)
     where
         F: FnMut(&mut T, &mut T) -> bool,
     {
-        let len = {
-            let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
-            dedup.len()
-        };
-        self.truncate(len);
+        let len = self.len();
+        if len <= 1 {
+            return;
+        }
+
+        /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */
+        struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> {
+            /* Offset of the element we want to check if it is duplicate */
+            read: usize,
+
+            /* Offset of the place where we want to place the non-duplicate
+             * when we find it. */
+            write: usize,
+
+            /* The Vec that would need correction if `same_bucket` panicked */
+            vec: &'a mut Vec<T, A>,
+        }
+
+        impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> {
+            fn drop(&mut self) {
+                /* This code gets executed when `same_bucket` panics */
+
+                /* SAFETY: invariant guarantees that `read - write`
+                 * and `len - read` never overflow and that the copy is always
+                 * in-bounds. */
+                unsafe {
+                    let ptr = self.vec.as_mut_ptr();
+                    let len = self.vec.len();
+
+                    /* How many items were left when `same_bucket` paniced.
+                     * Basically vec[read..].len() */
+                    let items_left = len.wrapping_sub(self.read);
+
+                    /* Pointer to first item in vec[write..write+items_left] slice */
+                    let dropped_ptr = ptr.add(self.write);
+                    /* Pointer to first item in vec[read..] slice */
+                    let valid_ptr = ptr.add(self.read);
+
+                    /* Copy `vec[read..]` to `vec[write..write+items_left]`.
+                     * The slices can overlap, so `copy_nonoverlapping` cannot be used */
+                    ptr::copy(valid_ptr, dropped_ptr, items_left);
+
+                    /* How many items have been already dropped
+                     * Basically vec[read..write].len() */
+                    let dropped = self.read.wrapping_sub(self.write);
+
+                    self.vec.set_len(len - dropped);
+                }
+            }
+        }
+
+        let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self };
+        let ptr = gap.vec.as_mut_ptr();
+
+        /* Drop items while going through Vec, it should be more efficient than
+         * doing slice partition_dedup + truncate */
+
+        /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr
+         * are always in-bounds and read_ptr never aliases prev_ptr */
+        unsafe {
+            while gap.read < len {
+                let read_ptr = ptr.add(gap.read);
+                let prev_ptr = ptr.add(gap.write.wrapping_sub(1));
+
+                if same_bucket(&mut *read_ptr, &mut *prev_ptr) {
+                    /* We have found duplicate, drop it in-place */
+                    ptr::drop_in_place(read_ptr);
+                } else {
+                    let write_ptr = ptr.add(gap.write);
+
+                    /* Because `read_ptr` can be equal to `write_ptr`, we either
+                     * have to use `copy` or conditional `copy_nonoverlapping`.
+                     * Looks like the first option is faster. */
+                    ptr::copy(read_ptr, write_ptr, 1);
+
+                    /* We have filled that place, so go further */
+                    gap.write += 1;
+                }
+
+                gap.read += 1;
+            }
+
+            /* Technically we could let `gap` clean up with its Drop, but
+             * when `same_bucket` is guaranteed to not panic, this bloats a little
+             * the codegen, so we just do it manually */
+            gap.vec.set_len(gap.write);
+            mem::forget(gap);
+        }
     }
 
     /// Appends an element to the back of a collection.
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 799499b9b77..11673ed8262 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -19,6 +19,7 @@
 #![feature(int_bits_const)]
 #![feature(vecdeque_binary_search)]
 #![feature(slice_group_by)]
+#![feature(slice_partition_dedup)]
 #![feature(vec_extend_from_within)]
 #![feature(vec_spare_capacity)]
 
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 1ba2315ca73..c142536cd2d 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -2102,6 +2102,132 @@ fn test_extend_from_within() {
     assert_eq!(v, ["a", "b", "c", "b", "c", "a", "b"]);
 }
 
+#[test]
+fn test_vec_dedup_by() {
+    let mut vec: Vec<i32> = vec![1, -1, 2, 3, 1, -5, 5, -2, 2];
+
+    vec.dedup_by(|a, b| a.abs() == b.abs());
+
+    assert_eq!(vec, [1, 2, 3, 1, -5, -2]);
+}
+
+#[test]
+fn test_vec_dedup_empty() {
+    let mut vec: Vec<i32> = Vec::new();
+
+    vec.dedup();
+
+    assert_eq!(vec, []);
+}
+
+#[test]
+fn test_vec_dedup_one() {
+    let mut vec = vec![12i32];
+
+    vec.dedup();
+
+    assert_eq!(vec, [12]);
+}
+
+#[test]
+fn test_vec_dedup_multiple_ident() {
+    let mut vec = vec![12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11];
+
+    vec.dedup();
+
+    assert_eq!(vec, [12, 11]);
+}
+
+#[test]
+fn test_vec_dedup_partialeq() {
+    #[derive(Debug)]
+    struct Foo(i32, i32);
+
+    impl PartialEq for Foo {
+        fn eq(&self, other: &Foo) -> bool {
+            self.0 == other.0
+        }
+    }
+
+    let mut vec = vec![Foo(0, 1), Foo(0, 5), Foo(1, 7), Foo(1, 9)];
+
+    vec.dedup();
+    assert_eq!(vec, [Foo(0, 1), Foo(1, 7)]);
+}
+
+#[test]
+fn test_vec_dedup() {
+    let mut vec: Vec<bool> = Vec::with_capacity(8);
+    let mut template = vec.clone();
+
+    for x in 0u8..255u8 {
+        vec.clear();
+        template.clear();
+
+        let iter = (0..8).map(move |bit| (x >> bit) & 1 == 1);
+        vec.extend(iter);
+        template.extend_from_slice(&vec);
+
+        let (dedup, _) = template.partition_dedup();
+        vec.dedup();
+
+        assert_eq!(vec, dedup);
+    }
+}
+
+#[test]
+fn test_vec_dedup_panicking() {
+    #[derive(Debug)]
+    struct Panic {
+        drop_counter: &'static AtomicU32,
+        value: bool,
+        index: usize,
+    }
+
+    impl PartialEq for Panic {
+        fn eq(&self, other: &Self) -> bool {
+            self.value == other.value
+        }
+    }
+
+    impl Drop for Panic {
+        fn drop(&mut self) {
+            let x = self.drop_counter.fetch_add(1, Ordering::SeqCst);
+            assert!(x != 4);
+        }
+    }
+
+    static DROP_COUNTER: AtomicU32 = AtomicU32::new(0);
+    let expected = [
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 },
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 },
+        Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 },
+        Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 },
+    ];
+    let mut vec = vec![
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 },
+        // these elements get deduplicated
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 1 },
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 2 },
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 3 },
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 4 },
+        // here it panics
+        Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 },
+        Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 },
+        Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 },
+    ];
+
+    let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+        vec.dedup();
+    }));
+
+    let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index);
+
+    if !ok {
+        panic!("expected: {:?}\ngot: {:?}\n", expected, vec);
+    }
+}
+
 // Regression test for issue #82533
 #[test]
 fn test_extend_from_within_panicing_clone() {
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index dcdf0192660..7bfa58d34ed 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -1,7 +1,13 @@
 //! Generic hashing support.
 //!
-//! This module provides a generic way to compute the hash of a value. The
-//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
+//! This module provides a generic way to compute the [hash] of a value.
+//! Hashes are most commonly used with [`HashMap`] and [`HashSet`].
+//!
+//! [hash]: https://en.wikipedia.org/wiki/Hash_function
+//! [`HashMap`]: ../../std/collections/struct.HashMap.html
+//! [`HashSet`]: ../../std/collections/struct.HashSet.html
+//!
+//! The simplest way to make a type hashable is to use `#[derive(Hash)]`:
 //!
 //! # Examples
 //!
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 233afa92389..ed32668456d 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -17,7 +17,7 @@ use crate::iter::{FromIterator, FusedIterator};
 use crate::ops::Index;
 use crate::sys;
 
-/// A hash map implemented with quadratic probing and SIMD lookup.
+/// A [hash map] implemented with quadratic probing and SIMD lookup.
 ///
 /// By default, `HashMap` uses a hashing algorithm selected to provide
 /// resistance against HashDoS attacks. The algorithm is randomly seeded, and a
@@ -62,6 +62,7 @@ use crate::sys;
 /// The original C++ version of SwissTable can be found [here], and this
 /// [CppCon talk] gives an overview of how the algorithm works.
 ///
+/// [hash map]: crate::collections#use-a-hashmap-when
 /// [hashing algorithms available on crates.io]: https://crates.io/keywords/hasher
 /// [SwissTable]: https://abseil.io/blog/20180927-swisstables
 /// [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 912e975aa0a..8c801b9f128 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -19,7 +19,7 @@ use super::map::{map_try_reserve_error, RandomState};
 // for `bucket.val` in the case of HashSet. I suppose we would need HKT
 // to get rid of it properly.
 
-/// A hash set implemented as a `HashMap` where the value is `()`.
+/// A [hash set] implemented as a `HashMap` where the value is `()`.
 ///
 /// As with the [`HashMap`] type, a `HashSet` requires that the elements
 /// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
@@ -105,6 +105,7 @@ use super::map::{map_try_reserve_error, RandomState};
 /// // use the values stored in the set
 /// ```
 ///
+/// [hash set]: crate::collections#use-the-set-variant-of-any-of-these-maps-when
 /// [`HashMap`]: crate::collections::HashMap
 /// [`RefCell`]: crate::cell::RefCell
 /// [`Cell`]: crate::cell::Cell
diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs
index d7bba50c76a..2a487fff54a 100644
--- a/library/std/src/sys/unix/stack_overflow.rs
+++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -39,6 +39,7 @@ impl Drop for Handler {
 ))]
 mod imp {
     use super::Handler;
+    use crate::io;
     use crate::mem;
     use crate::ptr;
 
@@ -149,11 +150,11 @@ mod imp {
             0,
         );
         if stackp == MAP_FAILED {
-            panic!("failed to allocate an alternative stack");
+            panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
         }
         let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
         if guard_result != 0 {
-            panic!("failed to set up alternative stack guard page");
+            panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error());
         }
         stackp.add(page_size())
     }
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 40c96307514..01a12dcf5a2 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -231,6 +231,7 @@ pub mod guard {
     use libc::{mmap, mprotect};
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
+    use crate::io;
     use crate::ops::Range;
     use crate::sync::atomic::{AtomicUsize, Ordering};
     use crate::sys::os;
@@ -361,12 +362,12 @@ pub mod guard {
                 0,
             );
             if result != stackaddr || result == MAP_FAILED {
-                panic!("failed to allocate a guard page");
+                panic!("failed to allocate a guard page: {}", io::Error::last_os_error());
             }
 
             let result = mprotect(stackaddr, page_size, PROT_NONE);
             if result != 0 {
-                panic!("failed to protect the guard page");
+                panic!("failed to protect the guard page: {}", io::Error::last_os_error());
             }
 
             let guardaddr = stackaddr as usize;
diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile
index ee727359f39..2f0496d7dd4 100644
--- a/src/ci/docker/host-x86_64/dist-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile
@@ -9,6 +9,8 @@ RUN . /scripts/android-ndk.sh && \
     download_ndk android-ndk-r15c-linux-x86_64.zip && \
     make_standalone_toolchain arm 14 && \
     make_standalone_toolchain x86 14 && \
+    make_standalone_toolchain arm 21 && \
+    make_standalone_toolchain x86 21 && \
     make_standalone_toolchain arm64 21 && \
     make_standalone_toolchain x86_64 21 && \
     remove_ndk
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 7bb3cb14516..de3a99f34fc 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -45,10 +45,10 @@ ENV \
     CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-8 \
     CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-8 \
     AR_x86_64_fortanix_unknown_sgx=ar \
-    CC_x86_64_fortanix_unknown_sgx=x86_64-fortanix-unknown-sgx-clang-11 \
-    CFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
-    CXX_x86_64_fortanix_unknown_sgx=x86_64-fortanix-unknown-sgx-clang++-11 \
-    CXXFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
+    CC_x86_64_fortanix_unknown_sgx=clang-11 \
+    CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
+    CXX_x86_64_fortanix_unknown_sgx=clang++-11 \
+    CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
     AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \
     CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \
     CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++ \
@@ -71,8 +71,6 @@ COPY host-x86_64/dist-various-2/build-solaris-toolchain.sh /tmp/
 RUN /tmp/build-solaris-toolchain.sh x86_64  amd64   solaris-i386
 RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
 COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
-COPY host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh /usr/bin/x86_64-fortanix-unknown-sgx-clang-11
-RUN ln -s /usr/bin/x86_64-fortanix-unknown-sgx-clang-11 /usr/bin/x86_64-fortanix-unknown-sgx-clang++-11
 RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
 
 COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
diff --git a/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh b/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh
deleted file mode 100755
index c4ff44c37b1..00000000000
--- a/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-args=("$@")
-
-for i in "${!args[@]}"; do
-    # x86_64-fortanix-unknown-sgx doesn't have a C sysroot for things like
-    # stdint.h and the C++ STL. Unlike GCC, clang will not use the host's
-    # sysroot instead. Force it.
-    if [ "${args[$i]}" = "--target=x86_64-fortanix-unknown-sgx" ]; then
-        args[$i]="--target=x86_64-unknown-linux-gnu"
-    fi
-done
-
-exec "${0/x86_64-fortanix-unknown-sgx-clang/clang}" "${args[@]}"
diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile
index 31583eaa8fe..af75ec5e24d 100644
--- a/src/test/run-make-fulldeps/coverage-reports/Makefile
+++ b/src/test/run-make-fulldeps/coverage-reports/Makefile
@@ -82,13 +82,13 @@ endif
 %: $(SOURCEDIR)/lib/%.rs
 	# Compile the test library with coverage instrumentation
 	$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
-			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/lib/$@.rs && echo "--edition=2018" ) \
+			$$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \
 			--crate-type rlib -Zinstrument-coverage
 
 %: $(SOURCEDIR)/%.rs
 	# Compile the test program with coverage instrumentation
 	$(RUSTC) $(SOURCEDIR)/$@.rs \
-			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && echo "--edition=2018" ) \
+			$$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \
 			-L "$(TMPDIR)" -Zinstrument-coverage
 
 	# Run it in order to generate some profiling data,
@@ -107,7 +107,7 @@ endif
 	# Run it through rustdoc as well to cover doctests
 	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \
 			$(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
-			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && echo "--edition=2018" ) \
+			$$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \
 			-L "$(TMPDIR)" -Zinstrument-coverage \
 			-Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
 
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt
index 824bddaa401..3f9403e6f70 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt
@@ -1,6 +1,6 @@
     1|       |#![allow(unused_assignments, dead_code)]
     2|       |
-    3|       |// require-rust-edition-2018
+    3|       |// compile-flags: --edition=2018
     4|       |
     5|      1|async fn c(x: u8) -> u8 {
     6|      1|    if x == 8 {
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt
new file mode 100644
index 00000000000..6148d89ed75
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt
@@ -0,0 +1,53 @@
+    1|       |// compile-flags: -Zinline-mir
+    2|       |
+    3|       |use std::fmt::Display;
+    4|       |
+    5|      1|fn main() {
+    6|      1|    permutations(&['a', 'b', 'c']);
+    7|      1|}
+    8|       |
+    9|       |#[inline(always)]
+   10|      1|fn permutations<T: Copy + Display>(xs: &[T]) {
+   11|      1|    let mut ys = xs.to_owned();
+   12|      1|    permutate(&mut ys, 0);
+   13|      1|}
+   14|       |
+   15|     16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+   16|     16|    let n = length(xs);
+   17|     16|    if k == n {
+   18|      6|        display(xs);
+   19|     10|    } else if k < n {
+   20|     15|        for i in k..n {
+                               ^10
+   21|     15|            swap(xs, i, k);
+   22|     15|            permutate(xs, k + 1);
+   23|     15|            swap(xs, i, k);
+   24|     15|        }
+   25|      0|    } else {
+   26|      0|        error();
+   27|      0|    }
+   28|     16|}
+   29|       |
+   30|     16|fn length<T>(xs: &[T]) -> usize {
+   31|     16|    xs.len()
+   32|     16|}
+   33|       |
+   34|       |#[inline]
+   35|     30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+   36|     30|    let t = xs[i];
+   37|     30|    xs[i] = xs[j];
+   38|     30|    xs[j] = t;
+   39|     30|}
+   40|       |
+   41|      6|fn display<T: Display>(xs: &[T]) {
+   42|     18|    for x in xs {
+   43|     18|        print!("{}", x);
+   44|     18|    }
+   45|      6|    println!();
+   46|      6|}
+   47|       |
+   48|       |#[inline(always)]
+   49|       |fn error() {
+   50|       |    panic!("error");
+   51|       |}
+
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 0c28305dd77..bc2f673349a 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
@@ -19,12 +19,12 @@
    18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
    19|      2|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
+  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
   ------------------
-  | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  | used_crate::used_only_from_bin_crate_generic_function::<&str>:
   |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   19|      1|}
diff --git a/src/test/run-make-fulldeps/coverage-spanview/Makefile b/src/test/run-make-fulldeps/coverage-spanview/Makefile
index cd54ac0ed4c..b0bfa7074db 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/Makefile
+++ b/src/test/run-make-fulldeps/coverage-spanview/Makefile
@@ -38,9 +38,7 @@ endif
 %: $(SOURCEDIR)/lib/%.rs
 	# Compile the test library with coverage instrumentation
 	$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
-			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/lib/$@.rs && \
-				echo "--edition=2018" \
-			) \
+			$$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \
 			--crate-type rlib \
 			-Ztrim-diagnostic-paths=no \
 			-Zinstrument-coverage \
@@ -70,9 +68,7 @@ endif
 %: $(SOURCEDIR)/%.rs
 	# Compile the test program with coverage instrumentation
 	$(RUSTC) $(SOURCEDIR)/$@.rs \
-			$$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && \
-				echo "--edition=2018" \
-			) \
+			$$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \
 			-L "$(TMPDIR)" \
 			-Ztrim-diagnostic-paths=no \
 			-Zinstrument-coverage \
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..6287516636e
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.display - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 40"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0,1⦊</span>fn display&lt;T: Display&gt;(xs: &amp;[T]) <span class="annotation">⦉@0,1</span></span></span><span class="code" style="--layer: 0">{</span></span>
+<span class="line"><span class="code" style="--layer: 0">    for </span><span><span class="code odd" style="--layer: 1" title="42:9-42:10: @8[1]: _13 = ((_9 as Some).0: &amp;T)
+42:9-42:10: @8[3]: _14 = _13
+42:9-42:10: @8[4]: _7 = move _14
+42:9-42:10: @8[5]: _8 = const ()
+42:9-42:10: @8[13]: FakeRead(ForLet, _16)"><span class="annotation">@6,8,9,10,11⦊</span>x<span class="annotation">⦉@6,8,9,10,11</span></span></span><span class="code" style="--layer: 0"> in </span><span><span class="code odd" style="--layer: 1" title="42:14-42:16: @8[12]: _16 = _7
+43:16-43:20: @8[20]: _47 = const display::&lt;T&gt;::promoted[2]
+43:16-43:20: @8[21]: _22 = &amp;(*_47)
+43:16-43:20: @8[22]: _21 = &amp;(*_22)
+43:16-43:20: @8[23]: _20 = move _21 as &amp;[&amp;str] (Pointer(Unsize))
+43:22-43:23: @8[31]: _29 = &amp;_16
+43:9-43:25: @8[32]: _28 = (move _29,)
+43:9-43:25: @8[34]: FakeRead(ForMatchedPlace, _28)
+43:9-43:25: @8[36]: _30 = (_28.0: &amp;&amp;T)
+43:9-43:25: @8[39]: _32 = &amp;(*_30)
+43:9-43:25: @8[41]: _33 = &lt;&amp;T as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;T, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+43:9-43:25: @8.Call: _31 = std::fmt::ArgumentV1::new::&lt;&amp;T&gt;(move _32, move _33) -&gt; [return: bb9, unwind: bb14]
+43:9-43:25: @9[2]: _27 = [move _31]
+43:9-43:25: @9[5]: _26 = &amp;_27
+43:9-43:25: @9[6]: _25 = &amp;(*_26)
+43:9-43:25: @9[7]: _24 = move _25 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+43:9-43:25: @9.Call: _19 = std::fmt::Arguments::new_v1(move _20, move _24) -&gt; [return: bb10, unwind: bb14]
+43:9-43:25: @10.Call: _18 = std::io::_print(move _19) -&gt; [return: bb11, unwind: bb14]
+42:17-44:6: @11[6]: _17 = const ()"><span class="annotation">@6,8,9,10,11⦊</span>xs {</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:14-42:16: @8[12]: _16 = _7
+43:16-43:20: @8[20]: _47 = const display::&lt;T&gt;::promoted[2]
+43:16-43:20: @8[21]: _22 = &amp;(*_47)
+43:16-43:20: @8[22]: _21 = &amp;(*_22)
+43:16-43:20: @8[23]: _20 = move _21 as &amp;[&amp;str] (Pointer(Unsize))
+43:22-43:23: @8[31]: _29 = &amp;_16
+43:9-43:25: @8[32]: _28 = (move _29,)
+43:9-43:25: @8[34]: FakeRead(ForMatchedPlace, _28)
+43:9-43:25: @8[36]: _30 = (_28.0: &amp;&amp;T)
+43:9-43:25: @8[39]: _32 = &amp;(*_30)
+43:9-43:25: @8[41]: _33 = &lt;&amp;T as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;T, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+43:9-43:25: @8.Call: _31 = std::fmt::ArgumentV1::new::&lt;&amp;T&gt;(move _32, move _33) -&gt; [return: bb9, unwind: bb14]
+43:9-43:25: @9[2]: _27 = [move _31]
+43:9-43:25: @9[5]: _26 = &amp;_27
+43:9-43:25: @9[6]: _25 = &amp;(*_26)
+43:9-43:25: @9[7]: _24 = move _25 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+43:9-43:25: @9.Call: _19 = std::fmt::Arguments::new_v1(move _20, move _24) -&gt; [return: bb10, unwind: bb14]
+43:9-43:25: @10.Call: _18 = std::io::_print(move _19) -&gt; [return: bb11, unwind: bb14]
+42:17-44:6: @11[6]: _17 = const ()">        print!("{}", x);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="42:14-42:16: @8[12]: _16 = _7
+43:16-43:20: @8[20]: _47 = const display::&lt;T&gt;::promoted[2]
+43:16-43:20: @8[21]: _22 = &amp;(*_47)
+43:16-43:20: @8[22]: _21 = &amp;(*_22)
+43:16-43:20: @8[23]: _20 = move _21 as &amp;[&amp;str] (Pointer(Unsize))
+43:22-43:23: @8[31]: _29 = &amp;_16
+43:9-43:25: @8[32]: _28 = (move _29,)
+43:9-43:25: @8[34]: FakeRead(ForMatchedPlace, _28)
+43:9-43:25: @8[36]: _30 = (_28.0: &amp;&amp;T)
+43:9-43:25: @8[39]: _32 = &amp;(*_30)
+43:9-43:25: @8[41]: _33 = &lt;&amp;T as std::fmt::Display&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;T, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+43:9-43:25: @8.Call: _31 = std::fmt::ArgumentV1::new::&lt;&amp;T&gt;(move _32, move _33) -&gt; [return: bb9, unwind: bb14]
+43:9-43:25: @9[2]: _27 = [move _31]
+43:9-43:25: @9[5]: _26 = &amp;_27
+43:9-43:25: @9[6]: _25 = &amp;(*_26)
+43:9-43:25: @9[7]: _24 = move _25 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+43:9-43:25: @9.Call: _19 = std::fmt::Arguments::new_v1(move _20, move _24) -&gt; [return: bb10, unwind: bb14]
+43:9-43:25: @10.Call: _18 = std::io::_print(move _19) -&gt; [return: bb11, unwind: bb14]
+42:17-44:6: @11[6]: _17 = const ()">    }<span class="annotation">⦉@6,8,9,10,11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    </span><span><span class="code even" style="--layer: 1" title="45:5-45:16: @5[13]: _46 = const display::&lt;T&gt;::promoted[1]
+45:5-45:16: @5[14]: _38 = &amp;(*_46)
+45:5-45:16: @5[15]: _37 = &amp;(*_38)
+45:5-45:16: @5[16]: _36 = move _37 as &amp;[&amp;str] (Pointer(Unsize))
+45:5-45:16: @5[22]: _44 = ()
+45:5-45:16: @5[23]: FakeRead(ForMatchedPlace, _44)
+45:5-45:16: @5[24]: _45 = const display::&lt;T&gt;::promoted[0]
+45:5-45:16: @5[25]: _42 = &amp;(*_45)
+45:5-45:16: @5[26]: _41 = &amp;(*_42)
+45:5-45:16: @5[27]: _40 = move _41 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+45:5-45:16: @5.Call: _35 = std::fmt::Arguments::new_v1(move _36, move _40) -&gt; [return: bb12, unwind: bb14]
+45:5-45:16: @12.Call: _34 = std::io::_print(move _35) -&gt; [return: bb13, unwind: bb14]
+46:2-46:2: @13.Return: return"><span class="annotation">@5,12,13⦊</span>println!();</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="45:5-45:16: @5[13]: _46 = const display::&lt;T&gt;::promoted[1]
+45:5-45:16: @5[14]: _38 = &amp;(*_46)
+45:5-45:16: @5[15]: _37 = &amp;(*_38)
+45:5-45:16: @5[16]: _36 = move _37 as &amp;[&amp;str] (Pointer(Unsize))
+45:5-45:16: @5[22]: _44 = ()
+45:5-45:16: @5[23]: FakeRead(ForMatchedPlace, _44)
+45:5-45:16: @5[24]: _45 = const display::&lt;T&gt;::promoted[0]
+45:5-45:16: @5[25]: _42 = &amp;(*_45)
+45:5-45:16: @5[26]: _41 = &amp;(*_42)
+45:5-45:16: @5[27]: _40 = move _41 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+45:5-45:16: @5.Call: _35 = std::fmt::Arguments::new_v1(move _36, move _40) -&gt; [return: bb12, unwind: bb14]
+45:5-45:16: @12.Call: _34 = std::io::_print(move _35) -&gt; [return: bb13, unwind: bb14]
+46:2-46:2: @13.Return: return">}<span class="annotation">⦉@5,12,13</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..bbf19c3e446
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.error - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 48"><span class="line"><span><span class="code even" style="--layer: 1" title="50:5-50:21: @0.Call: std::rt::begin_panic::&lt;&amp;str&gt;(const &quot;error&quot;) -&gt; bb1
+49:12-51:2: @1.Resume: resume"><span class="annotation">@0,1⦊</span>fn error() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="50:5-50:21: @0.Call: std::rt::begin_panic::&lt;&amp;str&gt;(const &quot;error&quot;) -&gt; bb1
+49:12-51:2: @1.Resume: resume">    panic!("error");</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="50:5-50:21: @0.Call: std::rt::begin_panic::&lt;&amp;str&gt;(const &quot;error&quot;) -&gt; bb1
+49:12-51:2: @1.Resume: resume">}<span class="annotation">⦉@0,1</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..8e8efb6d9f6
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.length - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 29"><span class="line"><span><span class="code even" style="--layer: 1" title="31:5-31:7: @0[1]: _2 = &amp;(*_1)
+31:5-31:13: @0.Call: _0 = core::slice::&lt;impl [T]&gt;::len(move _2) -&gt; [return: bb1, unwind: bb2]
+32:2-32:2: @1.Return: return"><span class="annotation">@0,1⦊</span>fn length&lt;T&gt;(xs: &amp;[T]) -&gt; usize {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:5-31:7: @0[1]: _2 = &amp;(*_1)
+31:5-31:13: @0.Call: _0 = core::slice::&lt;impl [T]&gt;::len(move _2) -&gt; [return: bb1, unwind: bb2]
+32:2-32:2: @1.Return: return">    xs.len()</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="31:5-31:7: @0[1]: _2 = &amp;(*_1)
+31:5-31:13: @0.Call: _0 = core::slice::&lt;impl [T]&gt;::len(move _2) -&gt; [return: bb1, unwind: bb2]
+32:2-32:2: @1.Return: return">}<span class="annotation">⦉@0,1</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..4ec2e9beede
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.main - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 4"><span class="line"><span><span class="code even" style="--layer: 1" title="6:18-6:34: @0[4]: _6 = const main::promoted[0]
+6:18-6:34: @0[5]: _4 = &amp;(*_6)
+6:18-6:34: @0[6]: _3 = &amp;(*_4)
+6:18-6:34: @0[7]: _2 = move _3 as &amp;[char] (Pointer(Unsize))
+6:5-6:35: @0.Call: _1 = permutations::&lt;char&gt;(move _2) -&gt; [return: bb1, unwind: bb2]
+5:11-7:2: @1[3]: _0 = const ()
+7:2-7:2: @1.Return: return"><span class="annotation">@0,1⦊</span>fn main() {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="6:18-6:34: @0[4]: _6 = const main::promoted[0]
+6:18-6:34: @0[5]: _4 = &amp;(*_6)
+6:18-6:34: @0[6]: _3 = &amp;(*_4)
+6:18-6:34: @0[7]: _2 = move _3 as &amp;[char] (Pointer(Unsize))
+6:5-6:35: @0.Call: _1 = permutations::&lt;char&gt;(move _2) -&gt; [return: bb1, unwind: bb2]
+5:11-7:2: @1[3]: _0 = const ()
+7:2-7:2: @1.Return: return">    permutations(&amp;['a', 'b', 'c']);</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="6:18-6:34: @0[4]: _6 = const main::promoted[0]
+6:18-6:34: @0[5]: _4 = &amp;(*_6)
+6:18-6:34: @0[6]: _3 = &amp;(*_4)
+6:18-6:34: @0[7]: _2 = move _3 as &amp;[char] (Pointer(Unsize))
+6:5-6:35: @0.Call: _1 = permutations::&lt;char&gt;(move _2) -&gt; [return: bb1, unwind: bb2]
+5:11-7:2: @1[3]: _0 = const ()
+7:2-7:2: @1.Return: return">}<span class="annotation">⦉@0,1</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..fd72973ccd0
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.permutate - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 14"><span class="line"><span><span class="code even" style="--layer: 1" title="16:20-16:22: @0[2]: _4 = &amp;(*_1)
+16:13-16:23: @0.Call: _3 = length::&lt;T&gt;(move _4) -&gt; [return: bb1, unwind: bb22]
+16:9-16:10: @1[1]: FakeRead(ForLet, _3)
+17:8-17:9: @1[4]: _6 = _2
+17:13-17:14: @1[6]: _7 = _3
+17:8-17:14: @1[7]: _5 = Eq(move _6, move _7)"><span class="annotation">@0,1⦊</span>fn permutate&lt;T: Copy + Display&gt;(xs: &amp;mut [T], k: usize) {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="16:20-16:22: @0[2]: _4 = &amp;(*_1)
+16:13-16:23: @0.Call: _3 = length::&lt;T&gt;(move _4) -&gt; [return: bb1, unwind: bb22]
+16:9-16:10: @1[1]: FakeRead(ForLet, _3)
+17:8-17:9: @1[4]: _6 = _2
+17:13-17:14: @1[6]: _7 = _3
+17:8-17:14: @1[7]: _5 = Eq(move _6, move _7)">    let n = length(xs);</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="16:20-16:22: @0[2]: _4 = &amp;(*_1)
+16:13-16:23: @0.Call: _3 = length::&lt;T&gt;(move _4) -&gt; [return: bb1, unwind: bb22]
+16:9-16:10: @1[1]: FakeRead(ForLet, _3)
+17:8-17:9: @1[4]: _6 = _2
+17:13-17:14: @1[6]: _7 = _3
+17:8-17:14: @1[7]: _5 = Eq(move _6, move _7)">    if k == n<span class="annotation">⦉@0,1</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="18:17-18:19: @2[2]: _9 = &amp;(*_1)
+18:9-18:20: @2.Call: _8 = display::&lt;T&gt;(move _9) -&gt; [return: bb4, unwind: bb22]
+17:15-19:6: @4[2]: _0 = const ()"><span class="annotation">@2,4⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:17-18:19: @2[2]: _9 = &amp;(*_1)
+18:9-18:20: @2.Call: _8 = display::&lt;T&gt;(move _9) -&gt; [return: bb4, unwind: bb22]
+17:15-19:6: @4[2]: _0 = const ()">        display(xs);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="18:17-18:19: @2[2]: _9 = &amp;(*_1)
+18:9-18:20: @2.Call: _8 = display::&lt;T&gt;(move _9) -&gt; [return: bb4, unwind: bb22]
+17:15-19:6: @4[2]: _0 = const ()">    }<span class="annotation">⦉@2,4</span></span></span><span class="code" style="--layer: 0"> else if </span><span><span class="code even" style="--layer: 1" title="19:15-19:16: @3[2]: _11 = _2
+19:19-19:20: @3[4]: _12 = _3
+19:15-19:20: @3[5]: _10 = Lt(move _11, move _12)"><span class="annotation">@3⦊</span>k &lt; n<span class="annotation">⦉@3</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        for </span><span><span class="code odd" style="--layer: 1" title="20:13-20:14: @14[1]: _25 = ((_21 as Some).0: usize)
+20:13-20:14: @14[3]: _26 = _25
+20:13-20:14: @14[4]: _19 = move _26
+20:13-20:14: @14[5]: _20 = const ()
+20:13-20:14: @14[13]: FakeRead(ForLet, _28)"><span class="annotation">@12,14,15,16,17,18⦊</span>i<span class="annotation">⦉@12,14,15,16,17,18</span></span></span><span class="code" style="--layer: 0"> in </span><span><span class="code even" style="--layer: 1" title="20:18-20:19: @5[3]: _15 = _2
+20:21-20:22: @5[5]: _16 = _3"><span class="annotation">@5,7⦊</span>k..n<span class="annotation">⦉@5,7</span></span></span><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="21:18-21:20: @14[17]: _31 = &amp;mut (*_1)
+21:22-21:23: @14[19]: _32 = _28
+21:25-21:26: @14[21]: _33 = _2
+21:13-21:27: @14.Call: _30 = swap::&lt;T&gt;(move _31, move _32, move _33) -&gt; [return: bb15, unwind: bb22]
+22:23-22:25: @15[6]: _35 = &amp;mut (*_1)
+22:27-22:28: @15[9]: _37 = _2
+22:27-22:32: @15[10]: _38 = CheckedAdd(_37, const 1_usize)
+22:27-22:32: @16[0]: _36 = move (_38.0: usize)
+22:13-22:33: @16.Call: _34 = permutate::&lt;T&gt;(move _35, move _36) -&gt; [return: bb17, unwind: bb22]
+23:18-23:20: @17[5]: _40 = &amp;mut (*_1)
+23:22-23:23: @17[7]: _41 = _28
+23:25-23:26: @17[9]: _42 = _2
+23:13-23:27: @17.Call: _39 = swap::&lt;T&gt;(move _40, move _41, move _42) -&gt; [return: bb18, unwind: bb22]
+20:23-24:10: @18[4]: _29 = const ()"><span class="annotation">@12,14,15,16,17,18⦊</span>{</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="21:18-21:20: @14[17]: _31 = &amp;mut (*_1)
+21:22-21:23: @14[19]: _32 = _28
+21:25-21:26: @14[21]: _33 = _2
+21:13-21:27: @14.Call: _30 = swap::&lt;T&gt;(move _31, move _32, move _33) -&gt; [return: bb15, unwind: bb22]
+22:23-22:25: @15[6]: _35 = &amp;mut (*_1)
+22:27-22:28: @15[9]: _37 = _2
+22:27-22:32: @15[10]: _38 = CheckedAdd(_37, const 1_usize)
+22:27-22:32: @16[0]: _36 = move (_38.0: usize)
+22:13-22:33: @16.Call: _34 = permutate::&lt;T&gt;(move _35, move _36) -&gt; [return: bb17, unwind: bb22]
+23:18-23:20: @17[5]: _40 = &amp;mut (*_1)
+23:22-23:23: @17[7]: _41 = _28
+23:25-23:26: @17[9]: _42 = _2
+23:13-23:27: @17.Call: _39 = swap::&lt;T&gt;(move _40, move _41, move _42) -&gt; [return: bb18, unwind: bb22]
+20:23-24:10: @18[4]: _29 = const ()">            swap(xs, i, k);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="21:18-21:20: @14[17]: _31 = &amp;mut (*_1)
+21:22-21:23: @14[19]: _32 = _28
+21:25-21:26: @14[21]: _33 = _2
+21:13-21:27: @14.Call: _30 = swap::&lt;T&gt;(move _31, move _32, move _33) -&gt; [return: bb15, unwind: bb22]
+22:23-22:25: @15[6]: _35 = &amp;mut (*_1)
+22:27-22:28: @15[9]: _37 = _2
+22:27-22:32: @15[10]: _38 = CheckedAdd(_37, const 1_usize)
+22:27-22:32: @16[0]: _36 = move (_38.0: usize)
+22:13-22:33: @16.Call: _34 = permutate::&lt;T&gt;(move _35, move _36) -&gt; [return: bb17, unwind: bb22]
+23:18-23:20: @17[5]: _40 = &amp;mut (*_1)
+23:22-23:23: @17[7]: _41 = _28
+23:25-23:26: @17[9]: _42 = _2
+23:13-23:27: @17.Call: _39 = swap::&lt;T&gt;(move _40, move _41, move _42) -&gt; [return: bb18, unwind: bb22]
+20:23-24:10: @18[4]: _29 = const ()">            permutate(xs, k + 1);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="21:18-21:20: @14[17]: _31 = &amp;mut (*_1)
+21:22-21:23: @14[19]: _32 = _28
+21:25-21:26: @14[21]: _33 = _2
+21:13-21:27: @14.Call: _30 = swap::&lt;T&gt;(move _31, move _32, move _33) -&gt; [return: bb15, unwind: bb22]
+22:23-22:25: @15[6]: _35 = &amp;mut (*_1)
+22:27-22:28: @15[9]: _37 = _2
+22:27-22:32: @15[10]: _38 = CheckedAdd(_37, const 1_usize)
+22:27-22:32: @16[0]: _36 = move (_38.0: usize)
+22:13-22:33: @16.Call: _34 = permutate::&lt;T&gt;(move _35, move _36) -&gt; [return: bb17, unwind: bb22]
+23:18-23:20: @17[5]: _40 = &amp;mut (*_1)
+23:22-23:23: @17[7]: _41 = _28
+23:25-23:26: @17[9]: _42 = _2
+23:13-23:27: @17.Call: _39 = swap::&lt;T&gt;(move _40, move _41, move _42) -&gt; [return: bb18, unwind: bb22]
+20:23-24:10: @18[4]: _29 = const ()">            swap(xs, i, k);</span></span>
+<span class="line"><span class="code odd" style="--layer: 1" title="21:18-21:20: @14[17]: _31 = &amp;mut (*_1)
+21:22-21:23: @14[19]: _32 = _28
+21:25-21:26: @14[21]: _33 = _2
+21:13-21:27: @14.Call: _30 = swap::&lt;T&gt;(move _31, move _32, move _33) -&gt; [return: bb15, unwind: bb22]
+22:23-22:25: @15[6]: _35 = &amp;mut (*_1)
+22:27-22:28: @15[9]: _37 = _2
+22:27-22:32: @15[10]: _38 = CheckedAdd(_37, const 1_usize)
+22:27-22:32: @16[0]: _36 = move (_38.0: usize)
+22:13-22:33: @16.Call: _34 = permutate::&lt;T&gt;(move _35, move _36) -&gt; [return: bb17, unwind: bb22]
+23:18-23:20: @17[5]: _40 = &amp;mut (*_1)
+23:22-23:23: @17[7]: _41 = _28
+23:25-23:26: @17[9]: _42 = _2
+23:13-23:27: @17.Call: _39 = swap::&lt;T&gt;(move _40, move _41, move _42) -&gt; [return: bb18, unwind: bb22]
+20:23-24:10: @18[4]: _29 = const ()">        }<span class="annotation">⦉@12,14,15,16,17,18</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">    } else </span><span><span class="code even" style="--layer: 1" title="26:9-26:16: @6.Call: _43 = error() -&gt; [return: bb19, unwind: bb22]
+25:12-27:6: @19[1]: _0 = const ()"><span class="annotation">@6,19⦊</span>{</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="26:9-26:16: @6.Call: _43 = error() -&gt; [return: bb19, unwind: bb22]
+25:12-27:6: @19[1]: _0 = const ()">        error();</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="26:9-26:16: @6.Call: _43 = error() -&gt; [return: bb19, unwind: bb22]
+25:12-27:6: @19[1]: _0 = const ()">    }<span class="annotation">⦉@6,19</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="28:2-28:2: @21.Return: return"><span class="annotation">@21⦊</span>‸<span class="annotation">⦉@21</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..4bfd22f3cd9
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.permutations - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 9"><span class="line"><span><span class="code even" style="--layer: 1" title="11:18-11:20: @0[2]: _3 = &amp;(*_1)
+11:18-11:31: @0.Call: _2 = &lt;[T] as std::borrow::ToOwned&gt;::to_owned(move _3) -&gt; [return: bb1, unwind: bb6]
+11:9-11:15: @1[1]: FakeRead(ForLet, _2)
+12:15-12:22: @1[7]: _8 = &amp;mut _2
+12:15-12:22: @1[8]: _7 = &amp;mut (*_8)
+12:15-12:22: @1.Call: _6 = &lt;std::vec::Vec&lt;T&gt; as std::ops::DerefMut&gt;::deref_mut(move _7) -&gt; [return: bb2, unwind: bb5]
+12:15-12:22: @2[0]: _5 = &amp;mut (*_6)
+12:5-12:26: @2.Call: _4 = permutate::&lt;T&gt;(move _5, const 0_usize) -&gt; [return: bb3, unwind: bb5]
+10:46-13:2: @3[4]: _0 = const ()
+13:2-13:2: @4.Return: return"><span class="annotation">@0,1,2,3,4⦊</span>fn permutations&lt;T: Copy + Display&gt;(xs: &amp;[T]) {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="11:18-11:20: @0[2]: _3 = &amp;(*_1)
+11:18-11:31: @0.Call: _2 = &lt;[T] as std::borrow::ToOwned&gt;::to_owned(move _3) -&gt; [return: bb1, unwind: bb6]
+11:9-11:15: @1[1]: FakeRead(ForLet, _2)
+12:15-12:22: @1[7]: _8 = &amp;mut _2
+12:15-12:22: @1[8]: _7 = &amp;mut (*_8)
+12:15-12:22: @1.Call: _6 = &lt;std::vec::Vec&lt;T&gt; as std::ops::DerefMut&gt;::deref_mut(move _7) -&gt; [return: bb2, unwind: bb5]
+12:15-12:22: @2[0]: _5 = &amp;mut (*_6)
+12:5-12:26: @2.Call: _4 = permutate::&lt;T&gt;(move _5, const 0_usize) -&gt; [return: bb3, unwind: bb5]
+10:46-13:2: @3[4]: _0 = const ()
+13:2-13:2: @4.Return: return">    let mut ys = xs.to_owned();</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="11:18-11:20: @0[2]: _3 = &amp;(*_1)
+11:18-11:31: @0.Call: _2 = &lt;[T] as std::borrow::ToOwned&gt;::to_owned(move _3) -&gt; [return: bb1, unwind: bb6]
+11:9-11:15: @1[1]: FakeRead(ForLet, _2)
+12:15-12:22: @1[7]: _8 = &amp;mut _2
+12:15-12:22: @1[8]: _7 = &amp;mut (*_8)
+12:15-12:22: @1.Call: _6 = &lt;std::vec::Vec&lt;T&gt; as std::ops::DerefMut&gt;::deref_mut(move _7) -&gt; [return: bb2, unwind: bb5]
+12:15-12:22: @2[0]: _5 = &amp;mut (*_6)
+12:5-12:26: @2.Call: _4 = permutate::&lt;T&gt;(move _5, const 0_usize) -&gt; [return: bb3, unwind: bb5]
+10:46-13:2: @3[4]: _0 = const ()
+13:2-13:2: @4.Return: return">    permutate(&amp;mut ys, 0);</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="11:18-11:20: @0[2]: _3 = &amp;(*_1)
+11:18-11:31: @0.Call: _2 = &lt;[T] as std::borrow::ToOwned&gt;::to_owned(move _3) -&gt; [return: bb1, unwind: bb6]
+11:9-11:15: @1[1]: FakeRead(ForLet, _2)
+12:15-12:22: @1[7]: _8 = &amp;mut _2
+12:15-12:22: @1[8]: _7 = &amp;mut (*_8)
+12:15-12:22: @1.Call: _6 = &lt;std::vec::Vec&lt;T&gt; as std::ops::DerefMut&gt;::deref_mut(move _7) -&gt; [return: bb2, unwind: bb5]
+12:15-12:22: @2[0]: _5 = &amp;mut (*_6)
+12:5-12:26: @2.Call: _4 = permutate::&lt;T&gt;(move _5, const 0_usize) -&gt; [return: bb3, unwind: bb5]
+10:46-13:2: @3[4]: _0 = const ()
+13:2-13:2: @4.Return: return">}<span class="annotation">⦉@0,1,2,3,4</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html
new file mode 100644
index 00000000000..4c3f63093d3
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<!--
+
+Preview this file as rendered HTML from the github source at:
+https://htmlpreview.github.io/?https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html
+
+For revisions in Pull Requests (PR):
+  * Replace "rust-lang" with the github PR author
+  * Replace "master" with the PR branch name
+
+-->
+<html>
+<head>
+<title>inline.swap - Coverage Spans</title>
+<style>
+    .line {
+        counter-increment: line;
+    }
+    .line:before {
+        content: counter(line) ": ";
+        font-family: Menlo, Monaco, monospace;
+        font-style: italic;
+        width: 3.8em;
+        display: inline-block;
+        text-align: right;
+        filter: opacity(50%);
+        -webkit-user-select: none;
+    }
+    .code {
+        color: #dddddd;
+        background-color: #222222;
+        font-family: Menlo, Monaco, monospace;
+        line-height: 1.4em;
+        border-bottom: 2px solid #222222;
+        white-space: pre;
+        display: inline-block;
+    }
+    .odd {
+        background-color: #55bbff;
+        color: #223311;
+    }
+    .even {
+        background-color: #ee7756;
+        color: #551133;
+    }
+    .code {
+        --index: calc(var(--layer) - 1);
+        padding-top: calc(var(--index) * 0.15em);
+        filter:
+            hue-rotate(calc(var(--index) * 25deg))
+            saturate(calc(100% - (var(--index) * 2%)))
+            brightness(calc(100% - (var(--index) * 1.5%)));
+    }
+    .annotation {
+        color: #4444ff;
+        font-family: monospace;
+        font-style: italic;
+        display: none;
+        -webkit-user-select: none;
+    }
+    body:active .annotation {
+        /* requires holding mouse down anywhere on the page */
+        display: inline-block;
+    }
+    span:hover .annotation {
+        /* requires hover over a span ONLY on its first line */
+        display: inline-block;
+    }
+</style>
+</head>
+<body>
+<div class="code" style="counter-reset: line 34"><span class="line"><span><span class="code even" style="--layer: 1" title="36:16-36:17: @0[2]: _5 = _2
+36:13-36:18: @0[3]: _6 = Len((*_1))
+36:13-36:18: @0[4]: _7 = Lt(_5, _6)
+36:13-36:18: @1[0]: _4 = (*_1)[_5]
+36:9-36:10: @1[1]: FakeRead(ForLet, _4)
+37:16-37:17: @1[5]: _9 = _3
+37:13-37:18: @1[6]: _10 = Len((*_1))
+37:13-37:18: @1[7]: _11 = Lt(_9, _10)
+37:13-37:18: @2[0]: _8 = (*_1)[_9]
+37:8-37:9: @2[2]: _12 = _2
+37:5-37:10: @2[3]: _13 = Len((*_1))
+37:5-37:10: @2[4]: _14 = Lt(_12, _13)
+37:5-37:18: @3[0]: (*_1)[_12] = move _8
+38:13-38:14: @3[5]: _15 = _4
+38:8-38:9: @3[7]: _16 = _3
+38:5-38:10: @3[8]: _17 = Len((*_1))
+38:5-38:10: @3[9]: _18 = Lt(_16, _17)
+38:5-38:14: @4[0]: (*_1)[_16] = move _15
+35:52-39:2: @4[3]: _0 = const ()
+39:2-39:2: @4.Return: return"><span class="annotation">@0,1,2,3,4⦊</span>fn swap&lt;T: Copy&gt;(xs: &amp;mut [T], i: usize, j: usize) {</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:16-36:17: @0[2]: _5 = _2
+36:13-36:18: @0[3]: _6 = Len((*_1))
+36:13-36:18: @0[4]: _7 = Lt(_5, _6)
+36:13-36:18: @1[0]: _4 = (*_1)[_5]
+36:9-36:10: @1[1]: FakeRead(ForLet, _4)
+37:16-37:17: @1[5]: _9 = _3
+37:13-37:18: @1[6]: _10 = Len((*_1))
+37:13-37:18: @1[7]: _11 = Lt(_9, _10)
+37:13-37:18: @2[0]: _8 = (*_1)[_9]
+37:8-37:9: @2[2]: _12 = _2
+37:5-37:10: @2[3]: _13 = Len((*_1))
+37:5-37:10: @2[4]: _14 = Lt(_12, _13)
+37:5-37:18: @3[0]: (*_1)[_12] = move _8
+38:13-38:14: @3[5]: _15 = _4
+38:8-38:9: @3[7]: _16 = _3
+38:5-38:10: @3[8]: _17 = Len((*_1))
+38:5-38:10: @3[9]: _18 = Lt(_16, _17)
+38:5-38:14: @4[0]: (*_1)[_16] = move _15
+35:52-39:2: @4[3]: _0 = const ()
+39:2-39:2: @4.Return: return">    let t = xs[i];</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:16-36:17: @0[2]: _5 = _2
+36:13-36:18: @0[3]: _6 = Len((*_1))
+36:13-36:18: @0[4]: _7 = Lt(_5, _6)
+36:13-36:18: @1[0]: _4 = (*_1)[_5]
+36:9-36:10: @1[1]: FakeRead(ForLet, _4)
+37:16-37:17: @1[5]: _9 = _3
+37:13-37:18: @1[6]: _10 = Len((*_1))
+37:13-37:18: @1[7]: _11 = Lt(_9, _10)
+37:13-37:18: @2[0]: _8 = (*_1)[_9]
+37:8-37:9: @2[2]: _12 = _2
+37:5-37:10: @2[3]: _13 = Len((*_1))
+37:5-37:10: @2[4]: _14 = Lt(_12, _13)
+37:5-37:18: @3[0]: (*_1)[_12] = move _8
+38:13-38:14: @3[5]: _15 = _4
+38:8-38:9: @3[7]: _16 = _3
+38:5-38:10: @3[8]: _17 = Len((*_1))
+38:5-38:10: @3[9]: _18 = Lt(_16, _17)
+38:5-38:14: @4[0]: (*_1)[_16] = move _15
+35:52-39:2: @4[3]: _0 = const ()
+39:2-39:2: @4.Return: return">    xs[i] = xs[j];</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:16-36:17: @0[2]: _5 = _2
+36:13-36:18: @0[3]: _6 = Len((*_1))
+36:13-36:18: @0[4]: _7 = Lt(_5, _6)
+36:13-36:18: @1[0]: _4 = (*_1)[_5]
+36:9-36:10: @1[1]: FakeRead(ForLet, _4)
+37:16-37:17: @1[5]: _9 = _3
+37:13-37:18: @1[6]: _10 = Len((*_1))
+37:13-37:18: @1[7]: _11 = Lt(_9, _10)
+37:13-37:18: @2[0]: _8 = (*_1)[_9]
+37:8-37:9: @2[2]: _12 = _2
+37:5-37:10: @2[3]: _13 = Len((*_1))
+37:5-37:10: @2[4]: _14 = Lt(_12, _13)
+37:5-37:18: @3[0]: (*_1)[_12] = move _8
+38:13-38:14: @3[5]: _15 = _4
+38:8-38:9: @3[7]: _16 = _3
+38:5-38:10: @3[8]: _17 = Len((*_1))
+38:5-38:10: @3[9]: _18 = Lt(_16, _17)
+38:5-38:14: @4[0]: (*_1)[_16] = move _15
+35:52-39:2: @4[3]: _0 = const ()
+39:2-39:2: @4.Return: return">    xs[j] = t;</span></span>
+<span class="line"><span class="code even" style="--layer: 1" title="36:16-36:17: @0[2]: _5 = _2
+36:13-36:18: @0[3]: _6 = Len((*_1))
+36:13-36:18: @0[4]: _7 = Lt(_5, _6)
+36:13-36:18: @1[0]: _4 = (*_1)[_5]
+36:9-36:10: @1[1]: FakeRead(ForLet, _4)
+37:16-37:17: @1[5]: _9 = _3
+37:13-37:18: @1[6]: _10 = Len((*_1))
+37:13-37:18: @1[7]: _11 = Lt(_9, _10)
+37:13-37:18: @2[0]: _8 = (*_1)[_9]
+37:8-37:9: @2[2]: _12 = _2
+37:5-37:10: @2[3]: _13 = Len((*_1))
+37:5-37:10: @2[4]: _14 = Lt(_12, _13)
+37:5-37:18: @3[0]: (*_1)[_12] = move _8
+38:13-38:14: @3[5]: _15 = _4
+38:8-38:9: @3[7]: _16 = _3
+38:5-38:10: @3[8]: _17 = Len((*_1))
+38:5-38:10: @3[9]: _18 = Lt(_16, _17)
+38:5-38:14: @4[0]: (*_1)[_16] = move _15
+35:52-39:2: @4[3]: _0 = const ()
+39:2-39:2: @4.Return: return">}<span class="annotation">⦉@0,1,2,3,4</span></span></span></span></div>
+</body>
+</html>
diff --git a/src/test/run-make-fulldeps/coverage/async.rs b/src/test/run-make-fulldeps/coverage/async.rs
index 5553af92465..d5ec32deac1 100644
--- a/src/test/run-make-fulldeps/coverage/async.rs
+++ b/src/test/run-make-fulldeps/coverage/async.rs
@@ -1,6 +1,6 @@
 #![allow(unused_assignments, dead_code)]
 
-// require-rust-edition-2018
+// compile-flags: --edition=2018
 
 async fn c(x: u8) -> u8 {
     if x == 8 {
diff --git a/src/test/run-make-fulldeps/coverage/inline.rs b/src/test/run-make-fulldeps/coverage/inline.rs
new file mode 100644
index 00000000000..9cfab9ddbad
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/inline.rs
@@ -0,0 +1,51 @@
+// compile-flags: -Zinline-mir
+
+use std::fmt::Display;
+
+fn main() {
+    permutations(&['a', 'b', 'c']);
+}
+
+#[inline(always)]
+fn permutations<T: Copy + Display>(xs: &[T]) {
+    let mut ys = xs.to_owned();
+    permutate(&mut ys, 0);
+}
+
+fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+    let n = length(xs);
+    if k == n {
+        display(xs);
+    } else if k < n {
+        for i in k..n {
+            swap(xs, i, k);
+            permutate(xs, k + 1);
+            swap(xs, i, k);
+        }
+    } else {
+        error();
+    }
+}
+
+fn length<T>(xs: &[T]) -> usize {
+    xs.len()
+}
+
+#[inline]
+fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+    let t = xs[i];
+    xs[i] = xs[j];
+    xs[j] = t;
+}
+
+fn display<T: Display>(xs: &[T]) {
+    for x in xs {
+        print!("{}", x);
+    }
+    println!();
+}
+
+#[inline(always)]
+fn error() {
+    panic!("error");
+}
diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr
new file mode 100644
index 00000000000..b1b61f0211a
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.arm.stderr
@@ -0,0 +1,14 @@
+error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:22:15
+   |
+LL |         asm!(".att_syntax noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+
+error: att syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:25:15
+   |
+LL |         asm!(".att_syntax bbb noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs
new file mode 100644
index 00000000000..9e9c7badfca
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.rs
@@ -0,0 +1,38 @@
+// revisions: x86_64 arm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+    unsafe {
+        asm!(".intel_syntax noprefix", "nop");
+        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        asm!(".intel_syntax aaa noprefix", "nop");
+        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+        asm!(".att_syntax noprefix", "nop");
+        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
+        //[arm]~^^ att syntax is the default syntax on this target
+        asm!(".att_syntax bbb noprefix", "nop");
+        //[x86_64]~^ ERROR using the .att_syntax directive may cause issues
+        //[arm]~^^ att syntax is the default syntax on this target
+        asm!(".intel_syntax noprefix; nop");
+        //[x86_64]~^ ERROR intel syntax is the default syntax on this target
+
+        asm!(
+            r"
+            .intel_syntax noprefix
+            nop"
+        );
+        //[x86_64]~^^^ ERROR intel syntax is the default syntax on this target
+    }
+}
diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr
new file mode 100644
index 00000000000..c54c2742a57
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.x86_64.stderr
@@ -0,0 +1,50 @@
+error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:18:15
+   |
+LL |         asm!(".intel_syntax noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+
+error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:20:15
+   |
+LL |         asm!(".intel_syntax aaa noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+
+error: using the .att_syntax directive may cause issues, use the att_syntax option instead
+  --> $DIR/inline-syntax.rs:22:15
+   |
+LL |         asm!(".att_syntax noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the assembler directive and replace it with options(att_syntax)
+   |
+LL |         asm!("", "nop", options(att_syntax));
+   |              --       ^^^^^^^^^^^^^^^^^^^^^
+
+error: using the .att_syntax directive may cause issues, use the att_syntax option instead
+  --> $DIR/inline-syntax.rs:25:15
+   |
+LL |         asm!(".att_syntax bbb noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the assembler directive and replace it with options(att_syntax)
+   |
+LL |         asm!("", "nop", options(att_syntax));
+   |              --       ^^^^^^^^^^^^^^^^^^^^^
+
+error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:28:15
+   |
+LL |         asm!(".intel_syntax noprefix; nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive
+
+error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues
+  --> $DIR/inline-syntax.rs:33:14
+   |
+LL |               .intel_syntax noprefix
+   |  ______________^
+LL | |             nop"
+   | |_ help: remove this assembler directive
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/lint/register-tool-lint.rs b/src/test/ui/lint/register-tool-lint.rs
new file mode 100644
index 00000000000..0ba5a37b167
--- /dev/null
+++ b/src/test/ui/lint/register-tool-lint.rs
@@ -0,0 +1,11 @@
+#![crate_type = "lib"]
+#![feature(register_tool)]
+#![register_tool(xyz)]
+#![warn(xyz::my_lint)] // this should not error
+#![warn(abc::my_lint)]
+//~^ ERROR unknown tool name `abc` found in scoped lint
+//~| HELP add `#![register_tool(abc)]`
+//~| ERROR unknown tool name `abc`
+//~| HELP add `#![register_tool(abc)]`
+//~| ERROR unknown tool name `abc`
+//~| HELP add `#![register_tool(abc)]`
diff --git a/src/test/ui/lint/register-tool-lint.stderr b/src/test/ui/lint/register-tool-lint.stderr
new file mode 100644
index 00000000000..750c74cec1e
--- /dev/null
+++ b/src/test/ui/lint/register-tool-lint.stderr
@@ -0,0 +1,27 @@
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0710`.
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
deleted file mode 100644
index 8ed7f25d2bb..00000000000
--- a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Ensures -Zmir-opt-level=3 (specifically, inlining) is not allowed with -Zinstrument-coverage.
-// Regression test for issue #80060.
-//
-// needs-profiler-support
-// build-pass
-// compile-flags: -Zmir-opt-level=3 -Zinstrument-coverage
-#[inline(never)]
-fn foo() {}
-
-pub fn baz() {
-    bar();
-}
-
-#[inline(always)]
-fn bar() {
-    foo();
-}
-
-fn main() {
-    bar();
-}
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
deleted file mode 100644
index d482afc395d..00000000000
--- a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-warning: `-Z mir-opt-level=3` (or any level > 1) enables function inlining, which is incompatible with `-Z instrument-coverage`. Inlining will be disabled.
-
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index 547329cfb1b..97f19b3da45 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -1,7 +1,8 @@
+// ignore-tidy-linelength
+
 fn main() {}
 
 extern "C" {
     pub pub fn foo();
-    //~^ ERROR visibility `pub` is not followed by an item
-    //~| ERROR non-item in item list
+    //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
 }
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 8d8122292ae..6ac27078ea3 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,21 +1,16 @@
-error: visibility `pub` is not followed by an item
-  --> $DIR/duplicate-visibility.rs:4:5
-   |
-LL |     pub pub fn foo();
-   |     ^^^ the visibility
-   |
-   = help: you likely meant to define an item, e.g., `pub fn foo() {}`
-
-error: non-item in item list
-  --> $DIR/duplicate-visibility.rs:4:9
+error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found keyword `pub`
+  --> $DIR/duplicate-visibility.rs:6:9
    |
 LL | extern "C" {
-   |            - item list starts here
+   |            - while parsing this item list starting here
 LL |     pub pub fn foo();
-   |         ^^^ non-item starts here
-...
+   |         ^^^
+   |         |
+   |         expected one of 9 possible tokens
+   |         help: visibility `pub` must come before `pub pub`: `pub pub pub`
+LL |
 LL | }
-   | - item list ends here
+   | - the item list ends here
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-76437-async.rs b/src/test/ui/parser/issue-76437-async.rs
new file mode 100644
index 00000000000..84ee3dd2112
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-async.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    async pub fn t() {}
+    //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~| HELP visibility `pub` must come before `async`
+}
diff --git a/src/test/ui/parser/issue-76437-async.stderr b/src/test/ui/parser/issue-76437-async.stderr
new file mode 100644
index 00000000000..2c9c2a8cfba
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-async.stderr
@@ -0,0 +1,11 @@
+error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+  --> $DIR/issue-76437-async.rs:4:11
+   |
+LL |     async pub fn t() {}
+   |     ------^^^
+   |     |     |
+   |     |     expected one of `extern`, `fn`, or `unsafe`
+   |     help: visibility `pub` must come before `async`: `pub async`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-76437-const-async-unsafe.rs b/src/test/ui/parser/issue-76437-const-async-unsafe.rs
new file mode 100644
index 00000000000..f1e06e4ad89
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const-async-unsafe.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    const async unsafe pub fn t() {}
+    //~^ ERROR expected one of `extern` or `fn`, found keyword `pub`
+    //~| HELP visibility `pub` must come before `const async unsafe`
+}
diff --git a/src/test/ui/parser/issue-76437-const-async-unsafe.stderr b/src/test/ui/parser/issue-76437-const-async-unsafe.stderr
new file mode 100644
index 00000000000..2e91beda116
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const-async-unsafe.stderr
@@ -0,0 +1,11 @@
+error: expected one of `extern` or `fn`, found keyword `pub`
+  --> $DIR/issue-76437-const-async-unsafe.rs:4:24
+   |
+LL |     const async unsafe pub fn t() {}
+   |     -------------------^^^
+   |     |                  |
+   |     |                  expected one of `extern` or `fn`
+   |     help: visibility `pub` must come before `const async unsafe`: `pub const async unsafe`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-76437-const-async.rs b/src/test/ui/parser/issue-76437-const-async.rs
new file mode 100644
index 00000000000..3c789fdcd02
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const-async.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    const async pub fn t() {}
+    //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~| HELP visibility `pub` must come before `const async`
+}
diff --git a/src/test/ui/parser/issue-76437-const-async.stderr b/src/test/ui/parser/issue-76437-const-async.stderr
new file mode 100644
index 00000000000..21b96c14d7d
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const-async.stderr
@@ -0,0 +1,11 @@
+error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+  --> $DIR/issue-76437-const-async.rs:4:17
+   |
+LL |     const async pub fn t() {}
+   |     ------------^^^
+   |     |           |
+   |     |           expected one of `extern`, `fn`, or `unsafe`
+   |     help: visibility `pub` must come before `const async`: `pub const async`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-76437-const.rs b/src/test/ui/parser/issue-76437-const.rs
new file mode 100644
index 00000000000..d3815a52346
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    const pub fn t() {}
+    //~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~| HELP visibility `pub` must come before `const`
+}
diff --git a/src/test/ui/parser/issue-76437-const.stderr b/src/test/ui/parser/issue-76437-const.stderr
new file mode 100644
index 00000000000..cf80d9a9037
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-const.stderr
@@ -0,0 +1,11 @@
+error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+  --> $DIR/issue-76437-const.rs:4:11
+   |
+LL |     const pub fn t() {}
+   |     ------^^^
+   |     |     |
+   |     |     expected one of `async`, `extern`, `fn`, or `unsafe`
+   |     help: visibility `pub` must come before `const`: `pub const`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-76437-pub-crate-unsafe.rs b/src/test/ui/parser/issue-76437-pub-crate-unsafe.rs
new file mode 100644
index 00000000000..daa1d120795
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-pub-crate-unsafe.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    unsafe pub(crate) fn t() {}
+    //~^ ERROR expected one of `extern` or `fn`, found keyword `pub`
+    //~| HELP visibility `pub(crate)` must come before `unsafe`
+}
diff --git a/src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr b/src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr
new file mode 100644
index 00000000000..fa8f13721c8
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-pub-crate-unsafe.stderr
@@ -0,0 +1,11 @@
+error: expected one of `extern` or `fn`, found keyword `pub`
+  --> $DIR/issue-76437-pub-crate-unsafe.rs:4:12
+   |
+LL |     unsafe pub(crate) fn t() {}
+   |     -------^^^-------
+   |     |      |
+   |     |      expected one of `extern` or `fn`
+   |     help: visibility `pub(crate)` must come before `unsafe`: `pub(crate) unsafe`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-76437-unsafe.rs b/src/test/ui/parser/issue-76437-unsafe.rs
new file mode 100644
index 00000000000..785a79a79a2
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-unsafe.rs
@@ -0,0 +1,7 @@
+// edition:2018
+
+mod t {
+    unsafe pub fn t() {}
+    //~^ ERROR expected one of `extern` or `fn`, found keyword `pub`
+    //~| HELP visibility `pub` must come before `unsafe`
+}
diff --git a/src/test/ui/parser/issue-76437-unsafe.stderr b/src/test/ui/parser/issue-76437-unsafe.stderr
new file mode 100644
index 00000000000..c63292ef853
--- /dev/null
+++ b/src/test/ui/parser/issue-76437-unsafe.stderr
@@ -0,0 +1,11 @@
+error: expected one of `extern` or `fn`, found keyword `pub`
+  --> $DIR/issue-76437-unsafe.rs:4:12
+   |
+LL |     unsafe pub fn t() {}
+   |     -------^^^
+   |     |      |
+   |     |      expected one of `extern` or `fn`
+   |     help: visibility `pub` must come before `unsafe`: `pub unsafe`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
new file mode 100644
index 00000000000..abc3d2691a3
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
@@ -0,0 +1,13 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Print)]
+enum ProceduralMasqueradeDummyType { //~ WARN using
+//~| WARN this was previously
+    Input
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
new file mode 100644
index 00000000000..0b930705e35
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
@@ -0,0 +1,25 @@
+warning: using `procedural-masquerade` crate
+  --> $DIR/issue-73933-procedural-masquerade.rs:8:6
+   |
+LL | enum ProceduralMasqueradeDummyType {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(proc_macro_back_compat)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+warning: 1 warning emitted
+
+Future incompatibility report: Future breakage date: None, diagnostic:
+warning: using `procedural-masquerade` crate
+  --> $DIR/issue-73933-procedural-masquerade.rs:8:6
+   |
+LL | enum ProceduralMasqueradeDummyType {
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(proc_macro_back_compat)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+   = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
new file mode 100644
index 00000000000..8edd68f8a3b
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
@@ -0,0 +1,22 @@
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #0 bytes(100..104),
+    },
+    Ident {
+        ident: "ProceduralMasqueradeDummyType",
+        span: #0 bytes(105..134),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "Input",
+                span: #0 bytes(186..191),
+            },
+        ],
+        span: #0 bytes(135..193),
+    },
+]
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
index 9c8540eede7..9e4aa7a939a 100644
--- a/src/test/ui/tool_lints.rs
+++ b/src/test/ui/tool_lints.rs
@@ -1,5 +1,5 @@
 #[warn(foo::bar)]
-//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
-//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
index 1bcd7fd735d..e06f6ddc1ca 100644
--- a/src/test/ui/tool_lints.stderr
+++ b/src/test/ui/tool_lints.stderr
@@ -1,20 +1,26 @@
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs
index 182aec34b47..84ab7c1944a 100644
--- a/src/test/ui/unknown-lint-tool-name.rs
+++ b/src/test/ui/unknown-lint-tool-name.rs
@@ -1,8 +1,8 @@
-#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+#![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 
-#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+#[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr
index 414816d229c..1d145515abf 100644
--- a/src/test/ui/unknown-lint-tool-name.stderr
+++ b/src/test/ui/unknown-lint-tool-name.stderr
@@ -1,38 +1,50 @@
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
 error: aborting due to 6 previous errors
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index b32a6f08638..1d4b5e1247d 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -44,7 +44,7 @@ fn main() {
     }
 
     if !config.has_tidy && config.mode == Mode::Rustdoc {
-        eprintln!("warning: `tidy` is not installed; generated diffs will be harder to read");
+        eprintln!("warning: `tidy` is not installed; diffs will not be generated");
     }
 
     log_config(&config);
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f3286d88366..7aa3d4ab09e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2367,6 +2367,9 @@ impl<'test> TestCx<'test> {
     }
 
     fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
+        if !self.config.has_tidy {
+            return;
+        }
         println!("info: generating a diff against nightly rustdoc");
 
         let suffix =
@@ -2428,10 +2431,8 @@ impl<'test> TestCx<'test> {
                 }
             }
         };
-        if self.config.has_tidy {
-            tidy_dir(out_dir);
-            tidy_dir(&compare_dir);
-        }
+        tidy_dir(out_dir);
+        tidy_dir(&compare_dir);
 
         let pager = {
             let output = Command::new("git").args(&["config", "--get", "core.pager"]).output().ok();