about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-26 19:17:00 +0000
committerbors <bors@rust-lang.org>2021-02-26 19:17:00 +0000
commit9c09c1f7cfcf9de0522bcd1cfda32b552195c464 (patch)
tree7fbf5611f6306f6ea0bb25d163d234cf17c3ac38
parentcecdb181ade91c0a5ffab9a148dba68fc7d00ee3 (diff)
parent0da9b474de36bf7954ceb51a0e483cc39e9d60da (diff)
downloadrust-9c09c1f7cfcf9de0522bcd1cfda32b552195c464.tar.gz
rust-9c09c1f7cfcf9de0522bcd1cfda32b552195c464.zip
Auto merge of #82552 - GuillaumeGomez:rollup-8dn1ztn, r=GuillaumeGomez
Rollup of 8 pull requests

Successful merges:

 - #81940 (Stabilize str_split_once)
 - #82165 (Reword labels on E0308 involving async fn return type)
 - #82456 (Replaced some unwrap_or and map_or with lazy variants)
 - #82491 (Consider inexpensive inlining criteria first)
 - #82506 (Properly account for non-shorthand pattern field in unused variable lint)
 - #82535 (Set codegen thread names)
 - #82545 (rustdoc: add optional woff2 versions of FiraSans.)
 - #82549 (Revert "Update normalize.css to 8.0.1")

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/metadata.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs124
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs2
-rw-r--r--compiler/rustc_macros/src/query.rs6
-rw-r--r--compiler/rustc_macros/src/session_diagnostic.rs6
-rw-r--r--compiler/rustc_mir/src/const_eval/eval_queries.rs2
-rw-r--r--compiler/rustc_mir/src/lib.rs1
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs270
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs15
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs2
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_span/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs9
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs5
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs2
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs6
-rw-r--r--compiler/rustc_typeck/src/collect.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/core/src/str/mod.rs8
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/test/src/lib.rs1
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/static/FiraSans-Medium.woff2bin0 -> 132780 bytes
-rw-r--r--src/librustdoc/html/static/FiraSans-Regular.woff2bin0 -> 129188 bytes
-rw-r--r--src/librustdoc/html/static/normalize.css2
-rw-r--r--src/librustdoc/html/static/rustdoc.css8
-rw-r--r--src/librustdoc/html/static_files.rs6
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/test/ui/async-await/dont-suggest-missing-await.stderr3
-rw-r--r--src/test/ui/async-await/generator-desc.stderr6
-rw-r--r--src/test/ui/async-await/issue-61076.rs3
-rw-r--r--src/test/ui/async-await/issue-61076.stderr3
-rw-r--r--src/test/ui/async-await/suggest-missing-await-closure.stderr3
-rw-r--r--src/test/ui/async-await/suggest-missing-await.stderr6
-rw-r--r--src/test/ui/lint/unused_variables-issue-82488.fixed16
-rw-r--r--src/test/ui/lint/unused_variables-issue-82488.rs16
-rw-r--r--src/test/ui/lint/unused_variables-issue-82488.stderr14
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr6
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr3
-rw-r--r--src/test/ui/suggestions/issue-81839.stderr3
-rw-r--r--src/test/ui/suggestions/match-prev-arm-needing-semi.rs9
-rw-r--r--src/test/ui/suggestions/match-prev-arm-needing-semi.stderr13
-rw-r--r--src/tools/linkchecker/main.rs2
-rw-r--r--src/tools/tidy/src/lib.rs2
53 files changed, 382 insertions, 247 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 170750461ca..1480ab25133 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -5,8 +5,7 @@
     associated_type_bounds,
     never_type,
     try_blocks,
-    hash_drain_filter,
-    str_split_once
+    hash_drain_filter
 )]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index d935fc83b72..1464784ae28 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -2372,7 +2372,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr
     fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
         let mut names = generics
             .parent
-            .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
+            .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
         names.extend(generics.params.iter().map(|param| param.name));
         names
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 955e739b2c1..c28b0d64651 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -481,9 +481,9 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
 
         fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
-            let mut names = generics
-                .parent
-                .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
+            let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
+                get_parameter_names(cx, cx.tcx.generics_of(def_id))
+            });
             names.extend(generics.params.iter().map(|param| param.name));
             names
         }
diff --git a/compiler/rustc_codegen_llvm/src/metadata.rs b/compiler/rustc_codegen_llvm/src/metadata.rs
index 3912d6a3a48..b007df57306 100644
--- a/compiler/rustc_codegen_llvm/src/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/metadata.rs
@@ -65,8 +65,8 @@ fn search_meta_section<'a>(
         while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
             let mut name_buf = None;
             let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
-            let name = name_buf.map_or(
-                String::new(), // We got a NULL ptr, ignore `name_len`.
+            let name = name_buf.map_or_else(
+                String::new, // We got a NULL ptr, ignore `name_len`.
                 |buf| {
                     String::from_utf8(
                         slice::from_raw_parts(buf.as_ptr() as *const u8, name_len as usize)
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 08932e26bf1..caa6a6a8e3a 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2082,7 +2082,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
         let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
         cmd.link_rust_dylib(
             Symbol::intern(&unlib(&sess.target, filestem)),
-            parent.unwrap_or(Path::new("")),
+            parent.unwrap_or_else(|| Path::new("")),
         );
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index d931c57fba2..7b8ce157fc2 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -712,6 +712,33 @@ impl<B: WriteBackendMethods> WorkItem<B> {
             }
         }
     }
+
+    /// Generate a short description of this work item suitable for use as a thread name.
+    fn short_description(&self) -> String {
+        // `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored.
+        // Use very short descriptions in this case to maximize the space available for the module name.
+        // Windows does not have that limitation so use slightly more descriptive names there.
+        match self {
+            WorkItem::Optimize(m) => {
+                #[cfg(windows)]
+                return format!("optimize module {}", m.name);
+                #[cfg(not(windows))]
+                return format!("opt {}", m.name);
+            }
+            WorkItem::CopyPostLtoArtifacts(m) => {
+                #[cfg(windows)]
+                return format!("copy LTO artifacts for {}", m.name);
+                #[cfg(not(windows))]
+                return format!("copy {}", m.name);
+            }
+            WorkItem::LTO(m) => {
+                #[cfg(windows)]
+                return format!("LTO module {}", m.name());
+                #[cfg(not(windows))]
+                return format!("LTO {}", m.name());
+            }
+        }
+    }
 }
 
 enum WorkItemResult<B: WriteBackendMethods> {
@@ -1609,56 +1636,59 @@ fn start_executing_work<B: ExtraBackendMethods>(
 pub struct WorkerFatalError;
 
 fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
-    thread::spawn(move || {
-        // Set up a destructor which will fire off a message that we're done as
-        // we exit.
-        struct Bomb<B: ExtraBackendMethods> {
-            coordinator_send: Sender<Box<dyn Any + Send>>,
-            result: Option<Result<WorkItemResult<B>, FatalError>>,
-            worker_id: usize,
-        }
-        impl<B: ExtraBackendMethods> Drop for Bomb<B> {
-            fn drop(&mut self) {
-                let worker_id = self.worker_id;
-                let msg = match self.result.take() {
-                    Some(Ok(WorkItemResult::Compiled(m))) => {
-                        Message::Done::<B> { result: Ok(m), worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsLink(m))) => {
-                        Message::NeedsLink::<B> { module: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
-                        Message::NeedsFatLTO::<B> { result: m, worker_id }
-                    }
-                    Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
-                        Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
-                    }
-                    Some(Err(FatalError)) => {
-                        Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
-                    }
-                    None => Message::Done::<B> { result: Err(None), worker_id },
-                };
-                drop(self.coordinator_send.send(Box::new(msg)));
+    let builder = thread::Builder::new().name(work.short_description());
+    builder
+        .spawn(move || {
+            // Set up a destructor which will fire off a message that we're done as
+            // we exit.
+            struct Bomb<B: ExtraBackendMethods> {
+                coordinator_send: Sender<Box<dyn Any + Send>>,
+                result: Option<Result<WorkItemResult<B>, FatalError>>,
+                worker_id: usize,
+            }
+            impl<B: ExtraBackendMethods> Drop for Bomb<B> {
+                fn drop(&mut self) {
+                    let worker_id = self.worker_id;
+                    let msg = match self.result.take() {
+                        Some(Ok(WorkItemResult::Compiled(m))) => {
+                            Message::Done::<B> { result: Ok(m), worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsLink(m))) => {
+                            Message::NeedsLink::<B> { module: m, worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
+                            Message::NeedsFatLTO::<B> { result: m, worker_id }
+                        }
+                        Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
+                            Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
+                        }
+                        Some(Err(FatalError)) => {
+                            Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+                        }
+                        None => Message::Done::<B> { result: Err(None), worker_id },
+                    };
+                    drop(self.coordinator_send.send(Box::new(msg)));
+                }
             }
-        }
 
-        let mut bomb = Bomb::<B> {
-            coordinator_send: cgcx.coordinator_send.clone(),
-            result: None,
-            worker_id: cgcx.worker,
-        };
+            let mut bomb = Bomb::<B> {
+                coordinator_send: cgcx.coordinator_send.clone(),
+                result: None,
+                worker_id: cgcx.worker,
+            };
 
-        // Execute the work itself, and if it finishes successfully then flag
-        // ourselves as a success as well.
-        //
-        // Note that we ignore any `FatalError` coming out of `execute_work_item`,
-        // as a diagnostic was already sent off to the main thread - just
-        // surface that there was an error in this worker.
-        bomb.result = {
-            let _prof_timer = work.start_profiling(&cgcx);
-            Some(execute_work_item(&cgcx, work))
-        };
-    });
+            // Execute the work itself, and if it finishes successfully then flag
+            // ourselves as a success as well.
+            //
+            // Note that we ignore any `FatalError` coming out of `execute_work_item`,
+            // as a diagnostic was already sent off to the main thread - just
+            // surface that there was an error in this worker.
+            bomb.result = {
+                let _prof_timer = work.start_profiling(&cgcx);
+                Some(execute_work_item(&cgcx, work))
+            };
+        })
+        .expect("failed to spawn thread");
 }
 
 enum SharedEmitterMessage {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9e55f7e5589..2d5f43e5890 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1484,13 +1484,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 for (key, values) in types.iter() {
                     let count = values.len();
                     let kind = key.descr();
+                    let mut returned_async_output_error = false;
                     for sp in values {
                         err.span_label(
                             *sp,
                             format!(
                                 "{}{}{} {}{}",
-                                if sp.is_desugaring(DesugaringKind::Async) {
-                                    "the `Output` of this `async fn`'s "
+                                if sp.is_desugaring(DesugaringKind::Async)
+                                    && !returned_async_output_error
+                                {
+                                    "checked the `Output` of this `async fn`, "
                                 } else if count == 1 {
                                     "the "
                                 } else {
@@ -1502,6 +1505,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                 pluralize!(count),
                             ),
                         );
+                        if sp.is_desugaring(DesugaringKind::Async)
+                            && returned_async_output_error == false
+                        {
+                            err.note("while checking the return type of the `async fn`");
+                            returned_async_output_error = true;
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index bfe37ce6959..5a271355817 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -201,7 +201,7 @@ fn check_panic_str<'tcx>(
             Some(v) if v.len() == 1 => "panic message contains a brace",
             _ => "panic message contains braces",
         };
-        cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or(vec![span]), |lint| {
+        cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
             let mut l = lint.build(msg);
             l.note("this message is not used as a format string, but will be in Rust 2021");
             if span.contains(arg.span) {
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 3e67525567f..291e7ef045e 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -378,14 +378,14 @@ fn add_query_description_impl(
                 let t = &(t.0).0;
                 quote! { #t }
             })
-            .unwrap_or(quote! { _ });
+            .unwrap_or_else(|| quote! { _ });
         let value = args
             .as_ref()
             .map(|t| {
                 let t = &(t.1).0;
                 quote! { #t }
             })
-            .unwrap_or(quote! { _ });
+            .unwrap_or_else(|| quote! { _ });
         // expr is a `Block`, meaning that `{ #expr }` gets expanded
         // to `{ { stmts... } }`, which triggers the `unused_braces` lint.
         quote! {
@@ -409,7 +409,7 @@ fn add_query_description_impl(
     };
 
     let (tcx, desc) = modifiers.desc;
-    let tcx = tcx.as_ref().map_or(quote! { _ }, |t| quote! { #t });
+    let tcx = tcx.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t });
 
     let desc = quote! {
         #[allow(unused_variables)]
diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs
index 5c061a9d3c7..8a0fce209b7 100644
--- a/compiler/rustc_macros/src/session_diagnostic.rs
+++ b/compiler/rustc_macros/src/session_diagnostic.rs
@@ -473,9 +473,9 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
                                         .map(
                                             |applicability_idx| quote!(#binding.#applicability_idx),
                                         )
-                                        .unwrap_or(quote!(
-                                            rustc_errors::Applicability::Unspecified
-                                        ));
+                                        .unwrap_or_else(|| {
+                                            quote!(rustc_errors::Applicability::Unspecified)
+                                        });
                                     return Ok((span, applicability));
                                 }
                                 throw_span_err!(
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index de898460368..fa234ff5feb 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs
@@ -50,7 +50,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 
     let name =
         with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id())));
-    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
+    let prom = cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p));
     trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
 
     ecx.push_stack_frame(
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 8b3881ef9de..508510a81e1 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -28,7 +28,6 @@ Rust MIR: a lowered representation of Rust.
 #![feature(or_patterns)]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
-#![feature(str_split_once)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index f4f69fc8ac6..16279040a1c 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -1,6 +1,6 @@
 //! Inlining pass for MIR functions
 
-use rustc_attr as attr;
+use rustc_attr::InlineAttr;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
@@ -106,72 +106,90 @@ struct Inliner<'tcx> {
 impl Inliner<'tcx> {
     fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>) {
         for bb in blocks {
-            let callsite = match self.get_valid_function_call(bb, &caller_body[bb], caller_body) {
+            let bb_data = &caller_body[bb];
+            if bb_data.is_cleanup {
+                continue;
+            }
+
+            let callsite = match self.resolve_callsite(caller_body, bb, bb_data) {
                 None => continue,
                 Some(it) => it,
             };
+
             let span = trace_span!("process_blocks", %callsite.callee, ?bb);
             let _guard = span.enter();
 
-            trace!(
-                "checking for self recursion ({:?} vs body_source: {:?})",
-                callsite.callee.def_id(),
-                caller_body.source.def_id()
-            );
-            if callsite.callee.def_id() == caller_body.source.def_id() {
-                debug!("Not inlining a function into itself");
-                continue;
-            }
-
-            if !self.is_mir_available(callsite.callee, caller_body) {
-                debug!("MIR unavailable {}", callsite.callee);
-                continue;
+            match self.try_inlining(caller_body, &callsite) {
+                Err(reason) => {
+                    debug!("not-inlined {} [{}]", callsite.callee, reason);
+                    continue;
+                }
+                Ok(new_blocks) => {
+                    debug!("inlined {}", callsite.callee);
+                    self.changed = true;
+                    self.history.push(callsite.callee);
+                    self.process_blocks(caller_body, new_blocks);
+                    self.history.pop();
+                }
             }
+        }
+    }
 
-            let span = trace_span!("instance_mir", %callsite.callee);
-            let instance_mir_guard = span.enter();
-            let callee_body = self.tcx.instance_mir(callsite.callee.def);
-            drop(instance_mir_guard);
-            if !self.should_inline(callsite, callee_body) {
-                continue;
-            }
+    /// Attempts to inline a callsite into the caller body. When successful returns basic blocks
+    /// containing the inlined body. Otherwise returns an error describing why inlining didn't take
+    /// place.
+    fn try_inlining(
+        &self,
+        caller_body: &mut Body<'tcx>,
+        callsite: &CallSite<'tcx>,
+    ) -> Result<std::ops::Range<BasicBlock>, &'static str> {
+        let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
+        self.check_codegen_attributes(callsite, callee_attrs)?;
+        self.check_mir_is_available(caller_body, &callsite.callee)?;
+        let callee_body = self.tcx.instance_mir(callsite.callee.def);
+        self.check_mir_body(callsite, callee_body, callee_attrs)?;
+
+        if !self.tcx.consider_optimizing(|| {
+            format!("Inline {:?} into {}", callee_body.span, callsite.callee)
+        }) {
+            return Err("optimization fuel exhausted");
+        }
 
-            if !self.tcx.consider_optimizing(|| {
-                format!("Inline {:?} into {}", callee_body.span, callsite.callee)
-            }) {
-                return;
-            }
+        let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions(
+            self.tcx,
+            self.param_env,
+            callee_body.clone(),
+        );
 
-            let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions(
-                self.tcx,
-                self.param_env,
-                callee_body.clone(),
-            );
+        let old_blocks = caller_body.basic_blocks().next_index();
+        self.inline_call(caller_body, &callsite, callee_body);
+        let new_blocks = old_blocks..caller_body.basic_blocks().next_index();
 
-            let old_blocks = caller_body.basic_blocks().next_index();
-            self.inline_call(callsite, caller_body, callee_body);
-            let new_blocks = old_blocks..caller_body.basic_blocks().next_index();
-            self.changed = true;
+        Ok(new_blocks)
+    }
 
-            self.history.push(callsite.callee);
-            self.process_blocks(caller_body, new_blocks);
-            self.history.pop();
+    fn check_mir_is_available(
+        &self,
+        caller_body: &Body<'tcx>,
+        callee: &Instance<'tcx>,
+    ) -> Result<(), &'static str> {
+        if callee.def_id() == caller_body.source.def_id() {
+            return Err("self-recursion");
         }
-    }
 
-    #[instrument(level = "debug", skip(self, caller_body))]
-    fn is_mir_available(&self, callee: Instance<'tcx>, caller_body: &Body<'tcx>) -> bool {
         match callee.def {
             InstanceDef::Item(_) => {
                 // If there is no MIR available (either because it was not in metadata or
                 // because it has no MIR because it's an extern function), then the inliner
                 // won't cause cycles on this.
                 if !self.tcx.is_mir_available(callee.def_id()) {
-                    return false;
+                    return Err("item MIR unavailable");
                 }
             }
             // These have no own callable MIR.
-            InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => return false,
+            InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => {
+                return Err("instance without MIR (intrinsic / virtual)");
+            }
             // This cannot result in an immediate cycle since the callee MIR is a shim, which does
             // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we
             // do not need to catch this here, we can wait until the inliner decides to continue
@@ -181,13 +199,13 @@ impl Inliner<'tcx> {
             | InstanceDef::FnPtrShim(..)
             | InstanceDef::ClosureOnceShim { .. }
             | InstanceDef::DropGlue(..)
-            | InstanceDef::CloneShim(..) => return true,
+            | InstanceDef::CloneShim(..) => return Ok(()),
         }
 
         if self.tcx.is_constructor(callee.def_id()) {
             trace!("constructors always have MIR");
             // Constructor functions cannot cause a query cycle.
-            return true;
+            return Ok(());
         }
 
         if let Some(callee_def_id) = callee.def_id().as_local() {
@@ -196,39 +214,44 @@ impl Inliner<'tcx> {
             // since their `optimized_mir` is used for layout computation, which can
             // create a cycle, even when no attempt is made to inline the function
             // in the other direction.
-            caller_body.generator_kind.is_none()
-                && (
-                    // Avoid a cycle here by only using `instance_mir` only if we have
-                    // a lower `HirId` than the callee. This ensures that the callee will
-                    // not inline us. This trick only works without incremental compilation.
-                    // So don't do it if that is enabled.
-                    !self.tcx.dep_graph.is_fully_enabled()
-                && self.hir_id < callee_hir_id
-                // If we know for sure that the function we're calling will itself try to
-                // call us, then we avoid inlining that function.
-                || !self.tcx.mir_callgraph_reachable((callee, caller_body.source.def_id().expect_local()))
-                )
+            if caller_body.generator_kind.is_some() {
+                return Err("local generator (query cycle avoidance)");
+            }
+
+            // Avoid a cycle here by only using `instance_mir` only if we have
+            // a lower `HirId` than the callee. This ensures that the callee will
+            // not inline us. This trick only works without incremental compilation.
+            // So don't do it if that is enabled.
+            if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id < callee_hir_id {
+                return Ok(());
+            }
+
+            // If we know for sure that the function we're calling will itself try to
+            // call us, then we avoid inlining that function.
+            if self
+                .tcx
+                .mir_callgraph_reachable((*callee, caller_body.source.def_id().expect_local()))
+            {
+                return Err("caller might be reachable from callee (query cycle avoidance)");
+            }
+
+            Ok(())
         } else {
             // This cannot result in an immediate cycle since the callee MIR is from another crate
             // and is already optimized. Any subsequent inlining may cause cycles, but we do
             // not need to catch this here, we can wait until the inliner decides to continue
             // inlining a second time.
             trace!("functions from other crates always have MIR");
-            true
+            Ok(())
         }
     }
 
-    fn get_valid_function_call(
+    fn resolve_callsite(
         &self,
+        caller_body: &Body<'tcx>,
         bb: BasicBlock,
         bb_data: &BasicBlockData<'tcx>,
-        caller_body: &Body<'tcx>,
     ) -> Option<CallSite<'tcx>> {
-        // Don't inline calls that are in cleanup blocks.
-        if bb_data.is_cleanup {
-            return None;
-        }
-
         // Only consider direct calls to functions
         let terminator = bb_data.terminator();
         if let TerminatorKind::Call { ref func, ref destination, .. } = terminator.kind {
@@ -258,73 +281,73 @@ impl Inliner<'tcx> {
         None
     }
 
-    #[instrument(level = "debug", skip(self, callee_body))]
-    fn should_inline(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> bool {
-        let tcx = self.tcx;
+    /// Returns an error if inlining is not possible based on codegen attributes alone. A success
+    /// indicates that inlining decision should be based on other criteria.
+    fn check_codegen_attributes(
+        &self,
+        callsite: &CallSite<'tcx>,
+        callee_attrs: &CodegenFnAttrs,
+    ) -> Result<(), &'satic str> {
+        if let InlineAttr::Never = callee_attrs.inline {
+            return Err("never inline hint");
+        }
+
+        // Only inline local functions if they would be eligible for cross-crate
+        // inlining. This is to ensure that the final crate doesn't have MIR that
+        // reference unexported symbols
+        if callsite.callee.def_id().is_local() {
+            let is_generic = callsite.callee.substs.non_erasable_generics().next().is_some();
+            if !is_generic && !callee_attrs.requests_inline() {
+                return Err("not exported");
+            }
+        }
 
         if callsite.fn_sig.c_variadic() {
-            debug!("callee is variadic - not inlining");
-            return false;
+            return Err("C variadic");
         }
 
-        let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
+        if callee_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+            return Err("naked");
+        }
 
-        let self_features = &self.codegen_fn_attrs.target_features;
-        let callee_features = &codegen_fn_attrs.target_features;
-        if callee_features.iter().any(|feature| !self_features.contains(feature)) {
-            debug!("`callee has extra target features - not inlining");
-            return false;
+        if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
+            return Err("cold");
         }
 
-        if self.codegen_fn_attrs.no_sanitize != codegen_fn_attrs.no_sanitize {
-            debug!("`callee has incompatible no_sanitize attribute - not inlining");
-            return false;
+        if callee_attrs.no_sanitize != self.codegen_fn_attrs.no_sanitize {
+            return Err("incompatible sanitizer set");
         }
 
-        if self.codegen_fn_attrs.instruction_set != codegen_fn_attrs.instruction_set {
-            debug!("`callee has incompatible instruction set - not inlining");
-            return false;
+        if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
+            return Err("incompatible instruction set");
         }
 
-        let hinted = match codegen_fn_attrs.inline {
-            // Just treat inline(always) as a hint for now,
-            // there are cases that prevent inlining that we
-            // need to check for first.
-            attr::InlineAttr::Always => true,
-            attr::InlineAttr::Never => {
-                debug!("`#[inline(never)]` present - not inlining");
-                return false;
-            }
-            attr::InlineAttr::Hint => true,
-            attr::InlineAttr::None => false,
-        };
-
-        // Only inline local functions if they would be eligible for cross-crate
-        // inlining. This is to ensure that the final crate doesn't have MIR that
-        // reference unexported symbols
-        if callsite.callee.def_id().is_local() {
-            if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted {
-                debug!("    callee is an exported function - not inlining");
-                return false;
+        for feature in &callee_attrs.target_features {
+            if !self.codegen_fn_attrs.target_features.contains(feature) {
+                return Err("incompatible target feature");
             }
         }
 
-        let mut threshold = if hinted {
+        Ok(())
+    }
+
+    /// Returns inlining decision that is based on the examination of callee MIR body.
+    /// Assumes that codegen attributes have been checked for compatibility already.
+    #[instrument(level = "debug", skip(self, callee_body))]
+    fn check_mir_body(
+        &self,
+        callsite: &CallSite<'tcx>,
+        callee_body: &Body<'tcx>,
+        callee_attrs: &CodegenFnAttrs,
+    ) -> Result<(), &'static str> {
+        let tcx = self.tcx;
+
+        let mut threshold = if callee_attrs.requests_inline() {
             self.tcx.sess.opts.debugging_opts.inline_mir_hint_threshold
         } else {
             self.tcx.sess.opts.debugging_opts.inline_mir_threshold
         };
 
-        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-            debug!("#[naked] present - not inlining");
-            return false;
-        }
-
-        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
-            debug!("#[cold] present - not inlining");
-            return false;
-        }
-
         // Give a bonus functions with a small number of blocks,
         // We normally have two or three blocks for even
         // very small functions.
@@ -393,11 +416,10 @@ impl Inliner<'tcx> {
                         if let Ok(Some(instance)) =
                             Instance::resolve(self.tcx, self.param_env, def_id, substs)
                         {
-                            if callsite.callee.def_id() == instance.def_id()
-                                || self.history.contains(&instance)
-                            {
-                                debug!("`callee is recursive - not inlining");
-                                return false;
+                            if callsite.callee.def_id() == instance.def_id() {
+                                return Err("self-recursion");
+                            } else if self.history.contains(&instance) {
+                                return Err("already inlined");
                             }
                         }
                         // Don't give intrinsics the extra penalty for calls
@@ -450,24 +472,24 @@ impl Inliner<'tcx> {
             }
         }
 
-        if let attr::InlineAttr::Always = codegen_fn_attrs.inline {
+        if let InlineAttr::Always = callee_attrs.inline {
             debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost);
-            true
+            Ok(())
         } else {
             if cost <= threshold {
                 debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold);
-                true
+                Ok(())
             } else {
                 debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold);
-                false
+                Err("cost above threshold")
             }
         }
     }
 
     fn inline_call(
         &self,
-        callsite: CallSite<'tcx>,
         caller_body: &mut Body<'tcx>,
+        callsite: &CallSite<'tcx>,
         mut callee_body: Body<'tcx>,
     ) {
         let terminator = caller_body[callsite.block].terminator.take().unwrap();
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 0f49386dec0..5b4939b7407 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
         fn tokens_to_string(tokens: &[TokenType]) -> String {
             let mut i = tokens.iter();
             // This might be a sign we need a connect method on `Iterator`.
-            let b = i.next().map_or(String::new(), |t| t.to_string());
+            let b = i.next().map_or_else(String::new, |t| t.to_string());
             i.enumerate().fold(b, |mut b, (i, a)| {
                 if tokens.len() > 2 && i == tokens.len() - 2 {
                     b.push_str(", or ");
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index c11dc231d48..82f19770a12 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -367,12 +367,17 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
-        let is_shorthand = matches!(param.pat.kind, rustc_hir::PatKind::Struct(..));
         param.pat.each_binding(|_bm, hir_id, _x, ident| {
-            let var = if is_shorthand {
-                Local(LocalInfo { id: hir_id, name: ident.name, is_shorthand: true })
-            } else {
-                Param(hir_id, ident.name)
+            let var = match param.pat.kind {
+                rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo {
+                    id: hir_id,
+                    name: ident.name,
+                    is_shorthand: fields
+                        .iter()
+                        .find(|f| f.ident == ident)
+                        .map_or(false, |f| f.is_shorthand),
+                }),
+                _ => Param(hir_id, ident.name),
             };
             self.add_variable(var);
         });
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index c0e4a1bdf07..493f25f4992 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1971,7 +1971,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         // Therefore, we would compute `object_lifetime_defaults` to a
         // vector like `['x, 'static]`. Note that the vector only
         // includes type parameters.
-        let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| {
+        let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
             let in_body = {
                 let mut scope = self.scope;
                 loop {
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 47f14fa6b7a..2df326628e7 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -169,7 +169,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
 
     // Check if sysroot is found using env::args().next(), and if is not found,
     // use env::current_exe() to imply sysroot.
-    from_env_args_next().unwrap_or(from_current_exe())
+    from_env_args_next().unwrap_or_else(from_current_exe)
 }
 
 // The name of the directory rustc expects libraries to be located.
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 36bf8634c6e..d002f597391 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,7 +1,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(once_cell)]
 #![feature(or_patterns)]
-#![feature(str_split_once)]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 4b03d38ccba..4dce029e86b 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -22,7 +22,6 @@
 #![feature(nll)]
 #![feature(min_specialization)]
 #![feature(option_expect_none)]
-#![feature(str_split_once)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 1ad57582eba..fb747dfcbd3 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -15,7 +15,6 @@
 #![feature(never_type)]
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
-#![feature(str_split_once)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 0133a961c11..264cc4f248c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -349,7 +349,7 @@ fn report_negative_positive_conflict(
         E0751,
         "found both positive and negative implementation of trait `{}`{}:",
         overlap.trait_desc,
-        overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty))
+        overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
     );
 
     match tcx.span_of_impl(negative_impl_def_id) {
@@ -397,7 +397,10 @@ fn report_conflicting_impls(
         let msg = format!(
             "conflicting implementations of trait `{}`{}:{}",
             overlap.trait_desc,
-            overlap.self_desc.clone().map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
+            overlap
+                .self_desc
+                .clone()
+                .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }),
             match used_to_be_allowed {
                 Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
                 _ => "",
@@ -415,7 +418,7 @@ fn report_conflicting_impls(
                     impl_span,
                     format!(
                         "conflicting implementation{}",
-                        overlap.self_desc.map_or(String::new(), |ty| format!(" for `{}`", ty))
+                        overlap.self_desc.map_or_else(String::new, |ty| format!(" for `{}`", ty))
                     ),
                 );
             }
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index c25aec5b2b7..38ff88553e8 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -1716,7 +1716,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             } else {
                 self.fcx
                     .associated_item(def_id, name, Namespace::ValueNS)
-                    .map_or(Vec::new(), |x| vec![x])
+                    .map_or_else(Vec::new, |x| vec![x])
             }
         } else {
             self.tcx.associated_items(def_id).in_definition_order().copied().collect()
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index fce7ae8119e..bb85336d7fb 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -1062,7 +1062,10 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) {
         E0533,
         "expected unit struct, unit variant or constant, found {}{}",
         res.descr(),
-        tcx.sess.source_map().span_to_snippet(span).map_or(String::new(), |s| format!(" `{}`", s)),
+        tcx.sess
+            .source_map()
+            .span_to_snippet(span)
+            .map_or_else(|_| String::new(), |s| format!(" `{}`", s)),
     )
     .emit();
 }
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 897b1f01569..f8ca916caf1 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -879,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let sm = tcx.sess.source_map();
             let path_str = sm
                 .span_to_snippet(sm.span_until_char(pat.span, '('))
-                .map_or(String::new(), |s| format!(" `{}`", s.trim_end()));
+                .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end()));
             let msg = format!(
                 "expected tuple struct or tuple variant, found {}{}",
                 res.descr(),
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 4f785982150..af82a3bb4f5 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -348,9 +348,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 let min_list_wb = min_list
                     .iter()
                     .map(|captured_place| {
-                        let locatable = captured_place.info.path_expr_id.unwrap_or(
-                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()),
-                        );
+                        let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| {
+                            self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local())
+                        });
 
                         self.resolve(captured_place.clone(), &locatable)
                     })
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index fc8e50b4b65..9fbc56f051b 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2387,7 +2387,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
                     .sess
                     .source_map()
                     .span_to_snippet(ast_ty.span)
-                    .map_or(String::new(), |s| format!(" `{}`", s));
+                    .map_or_else(|_| String::new(), |s| format!(" `{}`", s));
                 tcx.sess
                     .struct_span_err(
                         ast_ty.span,
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index dd98f806451..9c92d96dc70 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -6,7 +6,6 @@
 #![feature(exact_size_is_empty)]
 #![feature(new_uninit)]
 #![feature(pattern)]
-#![feature(str_split_once)]
 #![feature(trusted_len)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 6a35378ca7b..50ccc2a2eab 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1506,13 +1506,11 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_once)]
-    ///
     /// assert_eq!("cfg".split_once('='), None);
     /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo")));
     /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar")));
     /// ```
-    #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")]
+    #[stable(feature = "str_split_once", since = "1.52.0")]
     #[inline]
     pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> {
         let (start, end) = delimiter.into_searcher(self).next_match()?;
@@ -1525,13 +1523,11 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// #![feature(str_split_once)]
-    ///
     /// assert_eq!("cfg".rsplit_once('='), None);
     /// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo")));
     /// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar")));
     /// ```
-    #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")]
+    #[stable(feature = "str_split_once", since = "1.52.0")]
     #[inline]
     pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)>
     where
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 32aca8c8392..63b65d8b413 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -314,7 +314,6 @@
 #![feature(stdsimd)]
 #![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
-#![feature(str_split_once)]
 #![feature(test)]
 #![feature(thread_local)]
 #![feature(thread_local_internals)]
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index f9e65be9b0d..3415eaa9fb3 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -31,7 +31,6 @@
 #![feature(termination_trait_lib)]
 #![feature(test)]
 #![feature(total_cmp)]
-#![feature(str_split_once)]
 
 // Public reexports
 pub use self::bench::{black_box, Bencher};
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 6665f160dec..58e9e41e6a5 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -883,6 +883,8 @@ themePicker.onblur = handleThemeButtonsBlur;
         static_files::NORMALIZE_CSS,
         options.enable_minification,
     )?;
+    write(cx.dst.join("FiraSans-Regular.woff2"), static_files::fira_sans::REGULAR2)?;
+    write(cx.dst.join("FiraSans-Medium.woff2"), static_files::fira_sans::MEDIUM2)?;
     write(cx.dst.join("FiraSans-Regular.woff"), static_files::fira_sans::REGULAR)?;
     write(cx.dst.join("FiraSans-Medium.woff"), static_files::fira_sans::MEDIUM)?;
     write(cx.dst.join("FiraSans-LICENSE.txt"), static_files::fira_sans::LICENSE)?;
diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff2 b/src/librustdoc/html/static/FiraSans-Medium.woff2
new file mode 100644
index 00000000000..7a1e5fc548e
--- /dev/null
+++ b/src/librustdoc/html/static/FiraSans-Medium.woff2
Binary files differdiff --git a/src/librustdoc/html/static/FiraSans-Regular.woff2 b/src/librustdoc/html/static/FiraSans-Regular.woff2
new file mode 100644
index 00000000000..e766e06ccb0
--- /dev/null
+++ b/src/librustdoc/html/static/FiraSans-Regular.woff2
Binary files differdiff --git a/src/librustdoc/html/static/normalize.css b/src/librustdoc/html/static/normalize.css
index da9a75e3e85..0e042627918 100644
--- a/src/librustdoc/html/static/normalize.css
+++ b/src/librustdoc/html/static/normalize.css
@@ -1,2 +1,2 @@
 /* ignore-tidy-linelength */
-/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 56f17b7a616..e3d63fa2308 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -3,13 +3,17 @@
 	font-family: 'Fira Sans';
 	font-style: normal;
 	font-weight: 400;
-	src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
+	src: local('Fira Sans'),
+		url("FiraSans-Regular.woff2") format("woff2"),
+		url("FiraSans-Regular.woff") format('woff');
 }
 @font-face {
 	font-family: 'Fira Sans';
 	font-style: normal;
 	font-weight: 500;
-	src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
+	src: local('Fira Sans Medium'),
+		url("FiraSans-Medium.woff2") format("woff2"),
+		url("FiraSans-Medium.woff") format('woff');
 }
 
 /* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license. */
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 132ac42c422..701e106df67 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -76,9 +76,15 @@ crate mod fira_sans {
     /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
     crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");
 
+    /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
+    crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2");
+
     /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
     crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");
 
+    /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
+    crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2");
+
     /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
     crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
 }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d7978c4a022..2342ed3ab67 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -14,7 +14,6 @@
 #![feature(never_type)]
 #![feature(once_cell)]
 #![feature(type_ascription)]
-#![feature(str_split_once)]
 #![feature(iter_intersperse)]
 #![recursion_limit = "256"]
 #![deny(rustc::internal)]
diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr
index 14e72c2b1e7..654a3bcc92d 100644
--- a/src/test/ui/async-await/dont-suggest-missing-await.stderr
+++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr
@@ -2,11 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/dont-suggest-missing-await.rs:14:18
    |
 LL | async fn make_u32() -> u32 {
-   |                        --- the `Output` of this `async fn`'s found opaque type
+   |                        --- checked the `Output` of this `async fn`, found opaque type
 ...
 LL |         take_u32(x)
    |                  ^ expected `u32`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `u32`
            found opaque type `impl Future`
 help: consider `await`ing on the `Future`
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index b85926c7a03..04f191cc5e8 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -13,13 +13,15 @@ error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
    |
 LL | async fn one() {}
-   |                - the `Output` of this `async fn`'s expected opaque type
+   |                - checked the `Output` of this `async fn`, expected opaque type
 LL | async fn two() {}
-   |                - the `Output` of this `async fn`'s found opaque type
+   |                - checked the `Output` of this `async fn`, found opaque type
 ...
 LL |     fun(one(), two());
    |                ^^^^^ expected opaque type, found a different opaque type
    |
+   = note: while checking the return type of the `async fn`
+   = note: while checking the return type of the `async fn`
    = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>)
               found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>)
    = help: consider `await`ing on both `Future`s
diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs
index 8a7b166cb15..4a8e841b33d 100644
--- a/src/test/ui/async-await/issue-61076.rs
+++ b/src/test/ui/async-await/issue-61076.rs
@@ -56,7 +56,7 @@ async fn struct_() -> Struct {
 }
 
 async fn tuple() -> Tuple {
-    //~^ NOTE the `Output` of this `async fn`'s expected opaque type
+    //~^ NOTE checked the `Output` of this `async fn`, expected opaque type
     Tuple(1i32)
 }
 
@@ -92,6 +92,7 @@ async fn match_() {
         Tuple(_) => {} //~ ERROR mismatched types
         //~^ NOTE expected opaque type, found struct `Tuple`
         //~| NOTE expected opaque type `impl Future`
+        //~| NOTE while checking the return type of the `async fn`
     }
 }
 
diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr
index db6dc3ea00a..fd00522fac7 100644
--- a/src/test/ui/async-await/issue-61076.stderr
+++ b/src/test/ui/async-await/issue-61076.stderr
@@ -61,11 +61,12 @@ error[E0308]: mismatched types
   --> $DIR/issue-61076.rs:92:9
    |
 LL | async fn tuple() -> Tuple {
-   |                     ----- the `Output` of this `async fn`'s expected opaque type
+   |                     ----- checked the `Output` of this `async fn`, expected opaque type
 ...
 LL |         Tuple(_) => {}
    |         ^^^^^^^^ expected opaque type, found struct `Tuple`
    |
+   = note: while checking the return type of the `async fn`
    = note: expected opaque type `impl Future`
                    found struct `Tuple`
 help: consider `await`ing on the `Future`
diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr
index 2151057aa7f..483e52536a1 100644
--- a/src/test/ui/async-await/suggest-missing-await-closure.stderr
+++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr
@@ -2,11 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/suggest-missing-await-closure.rs:16:18
    |
 LL | async fn make_u32() -> u32 {
-   |                        --- the `Output` of this `async fn`'s found opaque type
+   |                        --- checked the `Output` of this `async fn`, found opaque type
 ...
 LL |         take_u32(x)
    |                  ^ expected `u32`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `u32`
            found opaque type `impl Future`
 help: consider `await`ing on the `Future`
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 26e81a52c21..14b5ee95ee8 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -2,11 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:12:14
    |
 LL | async fn make_u32() -> u32 {
-   |                        --- the `Output` of this `async fn`'s found opaque type
+   |                        --- checked the `Output` of this `async fn`, found opaque type
 ...
 LL |     take_u32(x)
    |              ^ expected `u32`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `u32`
            found opaque type `impl Future`
 help: consider `await`ing on the `Future`
@@ -18,11 +19,12 @@ error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:22:5
    |
 LL | async fn dummy() {}
-   |                  - the `Output` of this `async fn`'s found opaque type
+   |                  - checked the `Output` of this `async fn`, found opaque type
 ...
 LL |     dummy()
    |     ^^^^^^^ expected `()`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note: expected unit type `()`
             found opaque type `impl Future`
 help: consider `await`ing on the `Future`
diff --git a/src/test/ui/lint/unused_variables-issue-82488.fixed b/src/test/ui/lint/unused_variables-issue-82488.fixed
new file mode 100644
index 00000000000..3cb2c90d0d3
--- /dev/null
+++ b/src/test/ui/lint/unused_variables-issue-82488.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+#![deny(unused_variables)]
+
+struct Point {
+    x: u32,
+    y: u32
+}
+
+fn process_point(Point { x, y: _renamed }: Point) {
+//~^ ERROR unused variable: `renamed`
+    let _ = x;
+}
+
+fn main() {
+    process_point(Point { x: 0, y: 0 });
+}
diff --git a/src/test/ui/lint/unused_variables-issue-82488.rs b/src/test/ui/lint/unused_variables-issue-82488.rs
new file mode 100644
index 00000000000..007b0799bbb
--- /dev/null
+++ b/src/test/ui/lint/unused_variables-issue-82488.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+#![deny(unused_variables)]
+
+struct Point {
+    x: u32,
+    y: u32
+}
+
+fn process_point(Point { x, y: renamed }: Point) {
+//~^ ERROR unused variable: `renamed`
+    let _ = x;
+}
+
+fn main() {
+    process_point(Point { x: 0, y: 0 });
+}
diff --git a/src/test/ui/lint/unused_variables-issue-82488.stderr b/src/test/ui/lint/unused_variables-issue-82488.stderr
new file mode 100644
index 00000000000..dce03a0f738
--- /dev/null
+++ b/src/test/ui/lint/unused_variables-issue-82488.stderr
@@ -0,0 +1,14 @@
+error: unused variable: `renamed`
+  --> $DIR/unused_variables-issue-82488.rs:9:32
+   |
+LL | fn process_point(Point { x, y: renamed }: Point) {
+   |                                ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_renamed`
+   |
+note: the lint level is defined here
+  --> $DIR/unused_variables-issue-82488.rs:2:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 4fde243b2f8..2e513415e6c 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -189,9 +189,10 @@ LL |         async fn ft1();
 LL |         async fn ft1() {}
    |                        ^
    |                        |
-   |                        the `Output` of this `async fn`'s found opaque type
+   |                        checked the `Output` of this `async fn`, found opaque type
    |                        expected `()`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note: expected fn pointer `fn()`
               found fn pointer `fn() -> impl Future`
 
@@ -204,9 +205,10 @@ LL |         const async unsafe extern "C" fn ft5();
 LL |         const async unsafe extern "C" fn ft5() {}
    |                                                ^
    |                                                |
-   |                                                the `Output` of this `async fn`'s found opaque type
+   |                                                checked the `Output` of this `async fn`, found opaque type
    |                                                expected `()`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note: expected fn pointer `unsafe extern "C" fn()`
               found fn pointer `unsafe extern "C" fn() -> impl Future`
 
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
index 9b59e415011..4025b5030dc 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
@@ -53,9 +53,10 @@ LL |     async fn associated();
 LL |     async fn associated();
    |                          ^
    |                          |
-   |                          the `Output` of this `async fn`'s found opaque type
+   |                          checked the `Output` of this `async fn`, found opaque type
    |                          expected `()`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note: expected fn pointer `fn()`
               found fn pointer `fn() -> impl Future`
 
diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr
index 1a289d39e44..f9076587087 100644
--- a/src/test/ui/suggestions/issue-81839.stderr
+++ b/src/test/ui/suggestions/issue-81839.stderr
@@ -17,8 +17,9 @@ LL | |     }
   ::: $DIR/auxiliary/issue-81839.rs:6:49
    |
 LL |       pub async fn answer_str(&self, _s: &str) -> Test {
-   |                                                   ---- the `Output` of this `async fn`'s found opaque type
+   |                                                   ---- checked the `Output` of this `async fn`, found opaque type
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `()`
            found opaque type `impl Future`
 
diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs
index b8ac030b0bb..3b2cff3140d 100644
--- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs
+++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs
@@ -13,9 +13,9 @@ fn extra_semicolon() {
     };
 }
 
-async fn async_dummy() {} //~ NOTE the `Output` of this `async fn`'s found opaque type
-async fn async_dummy2() {} //~ NOTE the `Output` of this `async fn`'s found opaque type
-//~^ NOTE the `Output` of this `async fn`'s found opaque type
+async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
+//~| NOTE checked the `Output` of this `async fn`, found opaque type
 
 async fn async_extra_semicolon_same() {
     let _ = match true { //~ NOTE `match` arms have incompatible types
@@ -26,6 +26,7 @@ async fn async_extra_semicolon_same() {
         false => async_dummy(), //~ ERROR `match` arms have incompatible types
         //~^ NOTE expected `()`, found opaque type
         //~| NOTE expected type `()`
+        //~| NOTE while checking the return type of the `async fn`
         //~| HELP consider `await`ing on the `Future`
     };
 }
@@ -39,6 +40,7 @@ async fn async_extra_semicolon_different() {
         false => async_dummy2(), //~ ERROR `match` arms have incompatible types
         //~^ NOTE expected `()`, found opaque type
         //~| NOTE expected type `()`
+        //~| NOTE while checking the return type of the `async fn`
         //~| HELP consider `await`ing on the `Future`
     };
 }
@@ -51,6 +53,7 @@ async fn async_different_futures() {
         //~^ NOTE expected opaque type, found a different opaque type
         //~| NOTE expected type `impl Future`
         //~| NOTE distinct uses of `impl Trait` result in different opaque types
+        //~| NOTE while checking the return type of the `async fn`
     };
 }
 
diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
index fae0c498b44..e31ea9679b5 100644
--- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
+++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
@@ -2,7 +2,7 @@ error[E0308]: `match` arms have incompatible types
   --> $DIR/match-prev-arm-needing-semi.rs:26:18
    |
 LL |   async fn async_dummy() {}
-   |                          - the `Output` of this `async fn`'s found opaque type
+   |                          - checked the `Output` of this `async fn`, found opaque type
 ...
 LL |       let _ = match true {
    |  _____________-
@@ -18,6 +18,7 @@ LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `()`
            found opaque type `impl Future`
 help: consider `await`ing on the `Future`
@@ -30,10 +31,10 @@ LL |             async_dummy()
    |                         --
 
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/match-prev-arm-needing-semi.rs:39:18
+  --> $DIR/match-prev-arm-needing-semi.rs:40:18
    |
 LL |   async fn async_dummy2() {}
-   |                           - the `Output` of this `async fn`'s found opaque type
+   |                           - checked the `Output` of this `async fn`, found opaque type
 ...
 LL |       let _ = match true {
    |  _____________-
@@ -49,6 +50,7 @@ LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `()`
            found opaque type `impl Future`
 help: consider `await`ing on the `Future`
@@ -64,10 +66,10 @@ LL |         false => Box::new(async_dummy2()),
    |
 
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/match-prev-arm-needing-semi.rs:50:18
+  --> $DIR/match-prev-arm-needing-semi.rs:52:18
    |
 LL |   async fn async_dummy2() {}
-   |                           - the `Output` of this `async fn`'s found opaque type
+   |                           - checked the `Output` of this `async fn`, found opaque type
 ...
 LL |       let _ = match true {
    |  _____________-
@@ -81,6 +83,7 @@ LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
+   = note: while checking the return type of the `async fn`
    = note:     expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
            found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:17:25>)
    = note: distinct uses of `impl Trait` result in different opaque types
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 1ab3aead966..01e067ea0b8 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -14,7 +14,7 @@
 //! A few exceptions are allowed as there's known bugs in rustdoc, but this
 //! should catch the majority of "broken link" cases.
 
-#![feature(str_split_once)]
+#![cfg_attr(bootstrap, feature(str_split_once))]
 
 use std::collections::hash_map::Entry;
 use std::collections::{HashMap, HashSet};
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 27972c49924..11d36751f67 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -3,7 +3,7 @@
 //! This library contains the tidy lints and exposes it
 //! to be used by tools.
 
-#![feature(str_split_once)]
+#![cfg_attr(bootstrap, feature(str_split_once))]
 
 use std::fs::File;
 use std::io::Read;