about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-13 04:29:45 +0000
committerbors <bors@rust-lang.org>2021-01-13 04:29:45 +0000
commitfc93e4719c2ced744d75f0c281bb7ba29844bedd (patch)
tree8f137593f07f9ad050e78a3d37ce120357870e78
parent150d1fee04856ff158e34e8d687a7fe59e97ef33 (diff)
parent5b90fe1c3094050eecbb7be7440b398e98d0caa2 (diff)
downloadrust-fc93e4719c2ced744d75f0c281bb7ba29844bedd.tar.gz
rust-fc93e4719c2ced744d75f0c281bb7ba29844bedd.zip
Auto merge of #80960 - Dylan-DPC:rollup-89tri8x, r=Dylan-DPC
Rollup of 10 pull requests

Successful merges:

 - #78901 (diagnostics: Note capturing closures can't be coerced to fns)
 - #79588 (Provide more information for HRTB lifetime errors involving closures)
 - #80232 (Remove redundant def_id lookups)
 - #80662 (Added support for i386-unknown-linux-gnu and i486-unknown-linux-gnu)
 - #80736 (use Once instead of Mutex to manage capture resolution)
 - #80796 (Update to LLVM 11.0.1)
 - #80859 (Fix --pretty=expanded with --remap-path-prefix)
 - #80922 (Revert "Auto merge of #76896 - spastorino:codegen-inline-fns2)
 - #80924 (Fix rustdoc --test-builder argument parsing)
 - #80935 (Rename `rustc_middle::lint::LevelSource` to `LevelAndSource`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--.gitmodules2
-rw-r--r--compiler/rustc_driver/src/pretty.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs64
-rw-r--r--compiler/rustc_lint/src/levels.rs6
-rw-r--r--compiler/rustc_middle/src/lint.rs14
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs40
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs3
-rw-r--r--compiler/rustc_span/src/source_map.rs15
-rw-r--r--compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs1
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs34
-rw-r--r--library/std/src/backtrace.rs44
-rw-r--r--library/std/src/backtrace/tests.rs5
-rw-r--r--src/librustdoc/lib.rs6
m---------src/llvm-project0
-rw-r--r--src/test/incremental/hygiene/load_cached_hygiene.rs9
-rw-r--r--src/test/incremental/remapped_paths_cc/main.rs9
-rw-r--r--src/test/pretty/expanded-and-path-remap-80832.pp13
-rw-r--r--src/test/pretty/expanded-and-path-remap-80832.rs7
-rw-r--r--src/test/run-make-fulldeps/inline-always-many-cgu/Makefile7
-rw-r--r--src/test/rustdoc/issue-80893.rs6
-rw-r--r--src/test/ui/associated-types/higher-ranked-projection.bad.stderr7
-rw-r--r--src/test/ui/closures/closure-no-fn-1.stderr5
-rw-r--r--src/test/ui/closures/closure-no-fn-2.stderr5
-rw-r--r--src/test/ui/closures/closure-no-fn-4.rs8
-rw-r--r--src/test/ui/closures/closure-no-fn-4.stderr24
-rw-r--r--src/test/ui/closures/closure-no-fn-5.rs12
-rw-r--r--src/test/ui/closures/closure-no-fn-5.stderr23
-rw-r--r--src/test/ui/closures/closure-reform-bad.stderr5
-rw-r--r--src/test/ui/closures/print/closure-print-verbose.stderr5
-rw-r--r--src/test/ui/extern/extern-compare-with-return-type.rs5
-rw-r--r--src/test/ui/generator/resume-arg-late-bound.stderr32
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.stderr24
-rw-r--r--src/test/ui/issues/issue-26217.stderr2
-rw-r--r--src/test/ui/issues/issue-57843.stderr5
-rw-r--r--src/test/ui/lifetimes/issue-79187-2.nll.stderr44
-rw-r--r--src/test/ui/lifetimes/issue-79187-2.rs23
-rw-r--r--src/test/ui/lifetimes/issue-79187-2.stderr60
-rw-r--r--src/test/ui/lifetimes/issue-79187.nll.stderr14
-rw-r--r--src/test/ui/lifetimes/issue-79187.rs6
-rw-r--r--src/test/ui/lifetimes/issue-79187.stderr22
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr48
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr25
-rw-r--r--src/test/ui/unboxed-closures/issue-30906.stderr7
49 files changed, 660 insertions, 100 deletions
diff --git a/.gitmodules b/.gitmodules
index 984113151de..40e6fc2c19d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -37,7 +37,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/11.0-2020-10-12
+	branch = rustc/11.0-2021-01-05
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
 	url = https://github.com/rust-embedded/book.git
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 305fa838afa..b7edc24bc4a 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -363,8 +363,15 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
 
 fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
     let src_name = input.source_name();
-    let src =
-        String::clone(&sess.source_map().get_source_file(&src_name).unwrap().src.as_ref().unwrap());
+    let src = String::clone(
+        &sess
+            .source_map()
+            .get_source_file(&src_name)
+            .expect("get_source_file")
+            .src
+            .as_ref()
+            .expect("src"),
+    );
     (src, src_name)
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7b0a91986b3..5d56744805f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -98,7 +98,7 @@ pub(super) fn note_and_explain_region(
         // uh oh, hope no user ever sees THIS
         ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
 
-        ty::RePlaceholder(_) => ("any other region".to_string(), None),
+        ty::RePlaceholder(_) => return,
 
         // FIXME(#13998) RePlaceholder should probably print like
         // ReFree rather than dumping Debug output on the user.
@@ -1675,6 +1675,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.check_and_note_conflicting_crates(diag, terr);
         self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
 
+        if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
+            if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
+                if let Some(def_id) = def_id.as_local() {
+                    let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+                    let span = self.tcx.hir().span(hir_id);
+                    diag.span_note(span, "this closure does not fulfill the lifetime requirements");
+                }
+            }
+        }
+
         // It reads better to have the error origin as the final
         // thing.
         self.note_error_origin(diag, cause, exp_found);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 7fb94332cad..c88869abc29 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,6 +1,7 @@
 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
 use crate::infer::{self, InferCtxt, SubregionOrigin};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
+use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{self, Region};
 
@@ -107,14 +108,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 let mut err = self.report_and_explain_type_error(trace, &terr);
-                note_and_explain_region(self.tcx, &mut err, "", sup, "...");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...does not necessarily outlive ",
-                    sub,
-                    "",
-                );
+                match (sub, sup) {
+                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+                    (ty::RePlaceholder(_), _) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "",
+                            sup,
+                            " doesn't meet the lifetime requirements",
+                        );
+                    }
+                    (_, ty::RePlaceholder(_)) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "the required lifetime does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                    _ => {
+                        note_and_explain_region(self.tcx, &mut err, "", sup, "...");
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "...does not necessarily outlive ",
+                            sub,
+                            "",
+                        );
+                    }
+                }
                 err
             }
             infer::Reborrow(span) => {
@@ -286,13 +310,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         sup: Region<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
         // I can't think how to do better than this right now. -nikomatsakis
+        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
         match placeholder_origin {
+            infer::Subtype(box ref trace)
+                if matches!(
+                    &trace.cause.code.peel_derives(),
+                    ObligationCauseCode::BindingObligation(..)
+                ) =>
+            {
+                // Hack to get around the borrow checker because trace.cause has an `Rc`.
+                if let ObligationCauseCode::BindingObligation(_, span) =
+                    &trace.cause.code.peel_derives()
+                {
+                    let span = *span;
+                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+                    err.span_note(span, "the lifetime requirement is introduced here");
+                    err
+                } else {
+                    unreachable!()
+                }
+            }
             infer::Subtype(box trace) => {
                 let terr = TypeError::RegionsPlaceholderMismatch;
-                self.report_and_explain_type_error(trace, &terr)
+                return self.report_and_explain_type_error(trace, &terr);
             }
-
-            _ => self.report_concrete_failure(placeholder_origin, sub, sup),
+            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
         }
     }
 }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5cece569903..37bdc878b16 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::map::Map;
-use rustc_middle::lint::LevelSource;
+use rustc_middle::lint::LevelAndSource;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{
     struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
@@ -106,9 +106,9 @@ impl<'s> LintLevelsBuilder<'s> {
     /// diagnostic with no change to `specs`.
     fn insert_spec(
         &mut self,
-        specs: &mut FxHashMap<LintId, LevelSource>,
+        specs: &mut FxHashMap<LintId, LevelAndSource>,
         id: LintId,
-        (level, src): LevelSource,
+        (level, src): LevelAndSource,
     ) {
         // Setting to a non-forbid level is an error if the lint previously had
         // a forbid level. Note that this is not necessarily true even with a
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 64d850192f4..80c87dddd56 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -46,7 +46,7 @@ impl LintLevelSource {
 }
 
 /// A tuple of a lint level and its source.
-pub type LevelSource = (Level, LintLevelSource);
+pub type LevelAndSource = (Level, LintLevelSource);
 
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
@@ -57,11 +57,11 @@ pub enum LintSet {
     CommandLine {
         // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
         // flag.
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
     },
 
     Node {
-        specs: FxHashMap<LintId, LevelSource>,
+        specs: FxHashMap<LintId, LevelAndSource>,
         parent: u32,
     },
 }
@@ -75,9 +75,9 @@ impl LintLevelSets {
         &self,
         lint: &'static Lint,
         idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
-    ) -> LevelSource {
+    ) -> LevelAndSource {
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -113,7 +113,7 @@ impl LintLevelSets {
         &self,
         id: LintId,
         mut idx: u32,
-        aux: Option<&FxHashMap<LintId, LevelSource>>,
+        aux: Option<&FxHashMap<LintId, LevelAndSource>>,
     ) -> (Option<Level>, LintLevelSource) {
         if let Some(specs) = aux {
             if let Some(&(level, src)) = specs.get(&id) {
@@ -157,7 +157,7 @@ impl LintLevelMap {
         lint: &'static Lint,
         id: HirId,
         session: &Session,
-    ) -> Option<LevelSource> {
+    ) -> Option<LevelAndSource> {
         self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 698c2521596..f810f6a56a5 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,6 +1,7 @@
 use crate::dep_graph::{dep_constructor, DepNode, WorkProduct, WorkProductId};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
+use rustc_attr::InlineAttr;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -78,6 +79,14 @@ impl<'tcx> MonoItem<'tcx> {
     }
 
     pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
+        let generate_cgu_internal_copies = tcx
+            .sess
+            .opts
+            .debugging_opts
+            .inline_in_all_cgus
+            .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
+            && !tcx.sess.link_dead_code();
+
         match *self {
             MonoItem::Fn(ref instance) => {
                 let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
@@ -90,26 +99,21 @@ impl<'tcx> MonoItem<'tcx> {
                     return InstantiationMode::GloballyShared { may_conflict: false };
                 }
 
-                let generate_cgu_internal_copies = tcx
-                    .sess
-                    .opts
-                    .debugging_opts
-                    .inline_in_all_cgus
-                    .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
-                    && !tcx.sess.link_dead_code();
-
                 // At this point we don't have explicit linkage and we're an
-                // inlined function. If we should generate local copies for each CGU,
-                // then return `LocalCopy`, otherwise we'll just generate one copy
-                // and share it with all CGUs in this crate.
+                // inlined function. If we're inlining into all CGUs then we'll
+                // be creating a local copy per CGU.
                 if generate_cgu_internal_copies {
-                    InstantiationMode::LocalCopy
-                } else {
-                    // Finally, if we've reached this point, then we should optimize for
-                    // compilation speed. In that regard, we will ignore any `#[inline]`
-                    // annotations on the function and simply codegen it as usual. This could
-                    // conflict with upstream crates as it could be an exported symbol.
-                    InstantiationMode::GloballyShared { may_conflict: true }
+                    return InstantiationMode::LocalCopy;
+                }
+
+                // Finally, if this is `#[inline(always)]` we're sure to respect
+                // that with an inline copy per CGU, but otherwise we'll be
+                // creating one copy of this `#[inline]` function which may
+                // conflict with upstream crates as it could be an exported
+                // symbol.
+                match tcx.codegen_fn_attrs(instance.def_id()).inline {
+                    InlineAttr::Always => InstantiationMode::LocalCopy,
+                    _ => InstantiationMode::GloballyShared { may_conflict: true },
                 }
             }
             MonoItem::Static(..) | MonoItem::GlobalAsm(..) => {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 0af884a286d..041c040f0b7 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -92,8 +92,7 @@ impl<'tcx> Const<'tcx> {
                 let item_id = tcx.hir().get_parent_node(hir_id);
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id.to_def_id());
-                let index =
-                    generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id).to_def_id()];
+                let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
                 ty::ConstKind::Param(ty::ParamConst::new(index, name))
             }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 417f9bded09..625a0989ab3 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -813,8 +813,7 @@ fn convert_path_expr<'a, 'tcx>(
             let item_id = cx.tcx.hir().get_parent_node(hir_id);
             let item_def_id = cx.tcx.hir().local_def_id(item_id);
             let generics = cx.tcx.generics_of(item_def_id);
-            let local_def_id = cx.tcx.hir().local_def_id(hir_id);
-            let index = generics.param_def_id_to_index[&local_def_id.to_def_id()];
+            let index = generics.param_def_id_to_index[&def_id];
             let name = cx.tcx.hir().name(hir_id);
             let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 6635d44496c..a7b8c8ba1d4 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -872,8 +872,10 @@ impl SourceMap {
     }
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
+        // Remap filename before lookup
+        let filename = self.path_mapping().map_filename_prefix(filename).0;
         for sf in self.files.borrow().source_files.iter() {
-            if *filename == sf.name {
+            if filename == sf.name {
                 return Some(sf.clone());
             }
         }
@@ -1041,4 +1043,15 @@ impl FilePathMapping {
 
         (path, false)
     }
+
+    fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
+        match file {
+            FileName::Real(realfile) => {
+                let path = realfile.local_path();
+                let (path, mapped) = self.map_prefix(path.to_path_buf());
+                (FileName::Real(RealFileName::Named(path)), mapped)
+            }
+            other => (other.clone(), false),
+        }
+    }
 }
diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..f329b2d2c88
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i386".to_string();
+    base.llvm_target = "i386-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..5d96a558cb7
--- /dev/null
+++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs
@@ -0,0 +1,8 @@
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::i686_unknown_linux_gnu::target();
+    base.cpu = "i486".to_string();
+    base.llvm_target = "i486-unknown-linux-gnu".to_string();
+    base
+}
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 2728e03171a..c22f0017446 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -32,6 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
             return;
         }
+        self.suggest_no_capture_closure(err, expected, expr_ty);
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 17dbf989d66..9fbf330fe02 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -2,7 +2,7 @@ use super::FnCtxt;
 use crate::astconv::AstConv;
 
 use rustc_ast::util::parser::ExprPrecedence;
-use rustc_span::{self, Span};
+use rustc_span::{self, MultiSpan, Span};
 
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -287,6 +287,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// When encountering a closure that captures variables, where a FnPtr is expected,
+    /// suggest a non-capturing closure
+    pub(in super::super) fn suggest_no_capture_closure(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
+            if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
+                // Report upto four upvars being captured to reduce the amount error messages
+                // reported back to the user.
+                let spans_and_labels = upvars
+                    .iter()
+                    .take(4)
+                    .map(|(var_hir_id, upvar)| {
+                        let var_name = self.tcx.hir().name(*var_hir_id).to_string();
+                        let msg = format!("`{}` captured here", var_name);
+                        (upvar.span, msg)
+                    })
+                    .collect::<Vec<_>>();
+
+                let mut multi_span: MultiSpan =
+                    spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().into();
+                for (sp, label) in spans_and_labels {
+                    multi_span.push_span_label(sp, label);
+                }
+                err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
+            }
+        }
+    }
+
     /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
     pub(in super::super) fn suggest_calling_boxed_future_when_appropriate(
         &self,
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7e8e0a621e3..95e18ef2a65 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -95,11 +95,12 @@ mod tests;
 // a backtrace or actually symbolizing it.
 
 use crate::backtrace_rs::{self, BytesOrWideString};
+use crate::cell::UnsafeCell;
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sync::Mutex;
+use crate::sync::Once;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
 
@@ -132,7 +133,7 @@ pub enum BacktraceStatus {
 enum Inner {
     Unsupported,
     Disabled,
-    Captured(Mutex<Capture>),
+    Captured(LazilyResolvedCapture),
 }
 
 struct Capture {
@@ -171,12 +172,11 @@ enum BytesOrWide {
 
 impl fmt::Debug for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("<unsupported>"),
             Inner::Disabled => return fmt.write_str("<disabled>"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let frames = &capture.frames[capture.actual_start..];
 
@@ -331,7 +331,7 @@ impl Backtrace {
         let inner = if frames.is_empty() {
             Inner::Unsupported
         } else {
-            Inner::Captured(Mutex::new(Capture {
+            Inner::Captured(LazilyResolvedCapture::new(Capture {
                 actual_start: actual_start.unwrap_or(0),
                 frames,
                 resolved: false,
@@ -355,12 +355,11 @@ impl Backtrace {
 
 impl fmt::Display for Backtrace {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut capture = match &self.inner {
+        let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
             Inner::Disabled => return fmt.write_str("disabled backtrace"),
-            Inner::Captured(c) => c.lock().unwrap(),
+            Inner::Captured(c) => c.force(),
         };
-        capture.resolve();
 
         let full = fmt.alternate();
         let (frames, style) = if full {
@@ -404,6 +403,33 @@ impl fmt::Display for Backtrace {
     }
 }
 
+struct LazilyResolvedCapture {
+    sync: Once,
+    capture: UnsafeCell<Capture>,
+}
+
+impl LazilyResolvedCapture {
+    fn new(capture: Capture) -> Self {
+        LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
+    }
+
+    fn force(&self) -> &Capture {
+        self.sync.call_once(|| {
+            // SAFETY: This exclusive reference can't overlap with any others
+            // `Once` guarantees callers will block until this closure returns
+            // `Once` also guarantees only a single caller will enter this closure
+            unsafe { &mut *self.capture.get() }.resolve();
+        });
+
+        // SAFETY: This shared reference can't overlap with the exclusive reference above
+        unsafe { &*self.capture.get() }
+    }
+}
+
+// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
+// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
+unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
+
 impl Capture {
     fn resolve(&mut self) {
         // If we're already resolved, nothing to do!
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index f5f74d1eb9a..31cf0f70218 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -3,7 +3,7 @@ use super::*;
 #[test]
 fn test_debug() {
     let backtrace = Backtrace {
-        inner: Inner::Captured(Mutex::new(Capture {
+        inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
             actual_start: 1,
             resolved: true,
             frames: vec![
@@ -54,4 +54,7 @@ fn test_debug() {
     \n]";
 
     assert_eq!(format!("{:#?}", backtrace), expected);
+
+    // Format the backtrace a second time, just to make sure lazily resolved state is stable
+    assert_eq!(format!("{:#?}", backtrace), expected);
 }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7ed64c5813f..efcb006870c 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -412,11 +412,7 @@ fn opts() -> Vec<RustcOptGroup> {
             )
         }),
         unstable("test-builder", |o| {
-            o.optflag(
-                "",
-                "test-builder",
-                "specified the rustc-like binary to use as the test builder",
-            )
+            o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH")
         }),
         unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")),
     ]
diff --git a/src/llvm-project b/src/llvm-project
-Subproject fb115ee43b77601b237717c21ab0a8f5b5b9d50
+Subproject f9a8d70b6e0365ac2172ca6b7f1de0341297458
diff --git a/src/test/incremental/hygiene/load_cached_hygiene.rs b/src/test/incremental/hygiene/load_cached_hygiene.rs
index d6a5cb993a4..8124141418b 100644
--- a/src/test/incremental/hygiene/load_cached_hygiene.rs
+++ b/src/test/incremental/hygiene/load_cached_hygiene.rs
@@ -1,5 +1,5 @@
 // revisions:rpass1 rpass2
-// compile-flags: -Z query-dep-graph -O
+// compile-flags: -Z query-dep-graph
 // aux-build:cached_hygiene.rs
 
 // This tests the folllowing scenario
@@ -19,12 +19,7 @@
 // the metadata. Specifically, we were not resetting `orig_id`
 // for an `EpxnData` generate in the current crate, which would cause
 // us to serialize the `ExpnId` pointing to a garbage location in
-// the metadata.o
-
-// NOTE: We're explicitly passing the `-O` optimization flag because if optimizations are not
-// enabled, then rustc will ignore the `#[inline(always)]` attribute which means we do not load
-// the optimized mir for the unmodified function to be loaded and so the CGU containing that
-// function will be reused.
+// the metadata.
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs
index 735635029da..b01f02444ea 100644
--- a/src/test/incremental/remapped_paths_cc/main.rs
+++ b/src/test/incremental/remapped_paths_cc/main.rs
@@ -1,18 +1,11 @@
 // revisions:rpass1 rpass2 rpass3
-// compile-flags: -Z query-dep-graph -g -O
+// compile-flags: -Z query-dep-graph -g
 // aux-build:extern_crate.rs
 
 // ignore-asmjs wasm2js does not support source maps yet
-
 // This test case makes sure that we detect if paths emitted into debuginfo
 // are changed, even when the change happens in an external crate.
 
-// NOTE: We're explicitly passing the `-O` optimization flag because if no optimizations are
-// requested, rustc will ignore the `#[inline]` attribute. This is a performance optimization for
-// non-optimized builds which causes us to generate fewer copies of inlined functions when
-// runtime performance doesn't matter. Without this flag, the function will go into a different
-// CGU which can be reused by this crate.
-
 #![feature(rustc_attrs)]
 
 #![rustc_partition_reused(module="main", cfg="rpass2")]
diff --git a/src/test/pretty/expanded-and-path-remap-80832.pp b/src/test/pretty/expanded-and-path-remap-80832.pp
new file mode 100644
index 00000000000..6dbc19e9d9c
--- /dev/null
+++ b/src/test/pretty/expanded-and-path-remap-80832.pp
@@ -0,0 +1,13 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::v1::*;
+#[macro_use]
+extern crate std;
+// Test for issue 80832
+//
+// pretty-mode:expanded
+// pp-exact:expanded-and-path-remap-80832.pp
+// compile-flags: --remap-path-prefix {{src-base}}=the/src
+
+fn main() { }
diff --git a/src/test/pretty/expanded-and-path-remap-80832.rs b/src/test/pretty/expanded-and-path-remap-80832.rs
new file mode 100644
index 00000000000..f48441fbc57
--- /dev/null
+++ b/src/test/pretty/expanded-and-path-remap-80832.rs
@@ -0,0 +1,7 @@
+// Test for issue 80832
+//
+// pretty-mode:expanded
+// pp-exact:expanded-and-path-remap-80832.pp
+// compile-flags: --remap-path-prefix {{src-base}}=the/src
+
+fn main() {}
diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
index d12a23fbbf0..0cab955f644 100644
--- a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
+++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
@@ -1,12 +1,7 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=0
-	if ![cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b']; then \
-		echo "not found call instruction when one was expected"; \
-		exit 1; \
-	fi
-	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=1
+	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2
 	if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \
 		echo "found call instruction when one wasn't expected"; \
 		exit 1; \
diff --git a/src/test/rustdoc/issue-80893.rs b/src/test/rustdoc/issue-80893.rs
new file mode 100644
index 00000000000..7c958a80be3
--- /dev/null
+++ b/src/test/rustdoc/issue-80893.rs
@@ -0,0 +1,6 @@
+// compile-flags: --test -Z unstable-options --test-builder true
+
+/// ```no_run
+/// This tests that `--test-builder` is accepted as a flag by rustdoc.
+/// ```
+pub struct Foo;
diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
index 811c9a8f5e1..e2847b6b72b 100644
--- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
+++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr
@@ -2,10 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/higher-ranked-projection.rs:25:5
    |
 LL |     foo(());
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `&'a ()`
               found type `&()`
+note: the lifetime requirement is introduced here
+  --> $DIR/higher-ranked-projection.rs:15:33
+   |
+LL |     where for<'a> &'a T: Mirror<Image=U>
+   |                                 ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-no-fn-1.stderr b/src/test/ui/closures/closure-no-fn-1.stderr
index 76136315a1b..2b53802fea7 100644
--- a/src/test/ui/closures/closure-no-fn-1.stderr
+++ b/src/test/ui/closures/closure-no-fn-1.stderr
@@ -8,6 +8,11 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |
    = note: expected fn pointer `fn(u8) -> u8`
                  found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:50]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-1.rs:6:39
+   |
+LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+   |                                       ^ `a` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-no-fn-2.stderr b/src/test/ui/closures/closure-no-fn-2.stderr
index 85cbdbe7c18..ed9f87a2c94 100644
--- a/src/test/ui/closures/closure-no-fn-2.stderr
+++ b/src/test/ui/closures/closure-no-fn-2.stderr
@@ -8,6 +8,11 @@ LL |     let bar: fn() -> u8 = || { b };
    |
    = note: expected fn pointer `fn() -> u8`
                  found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:35]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-2.rs:6:32
+   |
+LL |     let bar: fn() -> u8 = || { b };
+   |                                ^ `b` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-no-fn-4.rs b/src/test/ui/closures/closure-no-fn-4.rs
new file mode 100644
index 00000000000..275bff645db
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-4.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let b = 2;
+    let _: fn(usize) -> usize = match true {
+        true => |a| a + 1,
+        false => |a| a - b,
+        //~^ ERROR `match` arms have incompatible types
+    };
+}
diff --git a/src/test/ui/closures/closure-no-fn-4.stderr b/src/test/ui/closures/closure-no-fn-4.stderr
new file mode 100644
index 00000000000..89798ec5dd3
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-4.stderr
@@ -0,0 +1,24 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/closure-no-fn-4.rs:5:18
+   |
+LL |       let _: fn(usize) -> usize = match true {
+   |  _________________________________-
+LL | |         true => |a| a + 1,
+   | |                 --------- this is found to be of type `fn(usize) -> usize`
+LL | |         false => |a| a - b,
+   | |                  ^^^^^^^^^ expected fn pointer, found closure
+LL | |
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected fn pointer `fn(usize) -> usize`
+                 found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:27]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-4.rs:5:26
+   |
+LL |         false => |a| a - b,
+   |                          ^ `b` captured here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-no-fn-5.rs b/src/test/ui/closures/closure-no-fn-5.rs
new file mode 100644
index 00000000000..43e3e977e34
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-5.rs
@@ -0,0 +1,12 @@
+// When providing diagnostics about not being able to coerce a capturing-closure
+// to fn type, we want to report only upto 4 captures.
+
+fn main() {
+    let a = 0u8;
+    let b = 0u8;
+    let c = 0u8;
+    let d = 0u8;
+    let e = 0u8;
+    let bar: fn() -> u8 = || { a; b; c; d; e };
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/closures/closure-no-fn-5.stderr b/src/test/ui/closures/closure-no-fn-5.stderr
new file mode 100644
index 00000000000..1f373f10489
--- /dev/null
+++ b/src/test/ui/closures/closure-no-fn-5.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/closure-no-fn-5.rs:10:27
+   |
+LL |     let bar: fn() -> u8 = || { a; b; c; d; e };
+   |              ----------   ^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
+   |              |
+   |              expected due to this
+   |
+   = note: expected fn pointer `fn() -> u8`
+                 found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:47]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-5.rs:10:32
+   |
+LL |     let bar: fn() -> u8 = || { a; b; c; d; e };
+   |                                ^  ^  ^  ^ `d` captured here
+   |                                |  |  |
+   |                                |  |  `c` captured here
+   |                                |  `b` captured here
+   |                                `a` captured here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
index 77c8c7ab794..37813879ce7 100644
--- a/src/test/ui/closures/closure-reform-bad.stderr
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -8,6 +8,11 @@ LL |     call_bare(f)
    |
    = note: expected fn pointer `for<'r> fn(&'r str)`
                  found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-reform-bad.rs:10:43
+   |
+LL |     let f = |s: &str| println!("{}{}", s, string);
+   |                                           ^^^^^^ `string` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr
index 9e07137a241..d19b07acbf1 100644
--- a/src/test/ui/closures/print/closure-print-verbose.stderr
+++ b/src/test/ui/closures/print/closure-print-verbose.stderr
@@ -8,6 +8,11 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |
    = note: expected fn pointer `fn(u8) -> u8`
                  found closure `[main::{closure#0} closure_substs=(unavailable)]`
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-print-verbose.rs:10:39
+   |
+LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
+   |                                       ^ `a` captured here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/extern/extern-compare-with-return-type.rs b/src/test/ui/extern/extern-compare-with-return-type.rs
index 6c9ed3760f6..52b51bb943a 100644
--- a/src/test/ui/extern/extern-compare-with-return-type.rs
+++ b/src/test/ui/extern/extern-compare-with-return-type.rs
@@ -2,8 +2,9 @@
 // Tests that we can compare various kinds of extern fn signatures.
 #![allow(non_camel_case_types)]
 
-extern fn voidret1() {}
-extern fn voidret2() {}
+// `dbg!()` differentiates these functions to ensure they won't be merged.
+extern fn voidret1() { dbg!() }
+extern fn voidret2() { dbg!() }
 
 extern fn uintret() -> usize { 22 }
 
diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr
index dc0864165ab..63411b59280 100644
--- a/src/test/ui/generator/resume-arg-late-bound.stderr
+++ b/src/test/ui/generator/resume-arg-late-bound.stderr
@@ -2,19 +2,47 @@ error[E0308]: mismatched types
   --> $DIR/resume-arg-late-bound.rs:15:5
    |
 LL |     test(gen);
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `for<'a> Generator<&'a mut bool>`
               found type `Generator<&mut bool>`
+note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined on the body at 11:15
+  --> $DIR/resume-arg-late-bound.rs:11:15
+   |
+LL |       let gen = |arg: &mut bool| {
+   |  _______________^
+LL | |         yield ();
+LL | |         *arg = true;
+LL | |     };
+   | |_____^
+note: the lifetime requirement is introduced here
+  --> $DIR/resume-arg-late-bound.rs:8:17
+   |
+LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/resume-arg-late-bound.rs:15:5
    |
 LL |     test(gen);
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `for<'a> Generator<&'a mut bool>`
               found type `Generator<&mut bool>`
+note: the anonymous lifetime #1 defined on the body at 11:15 doesn't meet the lifetime requirements
+  --> $DIR/resume-arg-late-bound.rs:11:15
+   |
+LL |       let gen = |arg: &mut bool| {
+   |  _______________^
+LL | |         yield ();
+LL | |         *arg = true;
+LL | |     };
+   | |_____^
+note: the lifetime requirement is introduced here
+  --> $DIR/resume-arg-late-bound.rs:8:17
+   |
+LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index 1ceb0c99e90..ed810d443be 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -2,19 +2,39 @@ error[E0308]: mismatched types
   --> $DIR/hrtb-perfect-forwarding.rs:46:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
+note: the required lifetime does not necessarily outlive the lifetime `'b` as defined on the function body at 39:21
+  --> $DIR/hrtb-perfect-forwarding.rs:39:21
+   |
+LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
+   |                     ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/hrtb-perfect-forwarding.rs:40:15
+   |
+LL |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/hrtb-perfect-forwarding.rs:46:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected type `Bar<&'a isize>`
               found type `Bar<&'b isize>`
+note: the lifetime `'b` as defined on the function body at 39:21 doesn't meet the lifetime requirements
+  --> $DIR/hrtb-perfect-forwarding.rs:39:21
+   |
+LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
+   |                     ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/hrtb-perfect-forwarding.rs:40:15
+   |
+LL |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+   |               ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr
index b1625536d42..f5c641be2d4 100644
--- a/src/test/ui/issues/issue-26217.stderr
+++ b/src/test/ui/issues/issue-26217.stderr
@@ -3,8 +3,6 @@ error[E0477]: the type `&'a i32` does not fulfill the required lifetime
    |
 LL |     foo::<&'a i32>();
    |     ^^^^^^^^^^^^^^
-   |
-   = note: type must outlive any other region
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr
index 01edb9507a3..7699e97da99 100644
--- a/src/test/ui/issues/issue-57843.stderr
+++ b/src/test/ui/issues/issue-57843.stderr
@@ -6,6 +6,11 @@ LL |     Foo(Box::new(|_| ()));
    |
    = note: expected type `FnOnce<(&'a bool,)>`
               found type `FnOnce<(&bool,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57843.rs:23:18
+   |
+LL |     Foo(Box::new(|_| ()));
+   |                  ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr
new file mode 100644
index 00000000000..4970c579e7b
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr
@@ -0,0 +1,44 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-79187-2.rs:9:24
+   |
+LL |     take_foo(|a: &i32| a);
+   |                  -   - ^ returning this value requires that `'1` must outlive `'2`
+   |                  |   |
+   |                  |   return type of closure is &'2 i32
+   |                  let's call the lifetime of this reference `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-79187-2.rs:10:34
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |                  -        -      ^ returning this value requires that `'1` must outlive `'2`
+   |                  |        |
+   |                  |        let's call the lifetime of this reference `'2`
+   |                  let's call the lifetime of this reference `'1`
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:9:5
+   |
+LL |     take_foo(|a: &i32| a);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187-2.rs:10:5
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-79187-2.rs b/src/test/ui/lifetimes/issue-79187-2.rs
new file mode 100644
index 00000000000..29d108facab
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.rs
@@ -0,0 +1,23 @@
+trait Foo {}
+
+impl<F> Foo for F where F: Fn(&i32) -> &i32 {}
+
+fn take_foo(_: impl Foo) {}
+
+fn main() {
+    take_foo(|a| a); //~ ERROR mismatched types
+    take_foo(|a: &i32| a); //~ ERROR mismatched types
+    take_foo(|a: &i32| -> &i32 { a }); //~ ERROR mismatched types
+
+    // OK
+    take_foo(identity(|a| a));
+    take_foo(identity(|a: &i32| a));
+    take_foo(identity(|a: &i32| -> &i32 { a }));
+
+    fn identity<F>(t: F) -> F
+    where
+        F: Fn(&i32) -> &i32,
+    {
+        t
+    }
+}
diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr
new file mode 100644
index 00000000000..a156c74fb33
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187-2.stderr
@@ -0,0 +1,60 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:8:5
+   |
+LL |     take_foo(|a| a);
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `for<'r> Fn<(&'r i32,)>`
+              found type `Fn<(&i32,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-79187-2.rs:8:14
+   |
+LL |     take_foo(|a| a);
+   |              ^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:9:5
+   |
+LL |     take_foo(|a: &i32| a);
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&i32`
+              found reference `&i32`
+note: the anonymous lifetime #1 defined on the body at 9:14 doesn't meet the lifetime requirements
+  --> $DIR/issue-79187-2.rs:9:14
+   |
+LL |     take_foo(|a: &i32| a);
+   |              ^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-79187-2.rs:10:5
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |     ^^^^^^^^ lifetime mismatch
+   |
+   = note: expected reference `&i32`
+              found reference `&i32`
+note: the anonymous lifetime #1 defined on the body at 10:14 doesn't meet the lifetime requirements
+  --> $DIR/issue-79187-2.rs:10:14
+   |
+LL |     take_foo(|a: &i32| -> &i32 { a });
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187-2.rs:5:21
+   |
+LL | fn take_foo(_: impl Foo) {}
+   |                     ^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr
new file mode 100644
index 00000000000..aa8809dbc95
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.nll.stderr
@@ -0,0 +1,14 @@
+error: higher-ranked subtype error
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lifetimes/issue-79187.rs b/src/test/ui/lifetimes/issue-79187.rs
new file mode 100644
index 00000000000..bf331d8a606
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.rs
@@ -0,0 +1,6 @@
+fn thing(x: impl FnOnce(&u32)) {}
+
+fn main() {
+    let f = |_| ();
+    thing(f); //~ERROR mismatched types
+}
diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr
new file mode 100644
index 00000000000..63f501e08fc
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-79187.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79187.rs:5:5
+   |
+LL |     thing(f);
+   |     ^^^^^ lifetime mismatch
+   |
+   = note: expected type `FnOnce<(&u32,)>`
+              found type `FnOnce<(&u32,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-79187.rs:4:13
+   |
+LL |     let f = |_| ();
+   |             ^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-79187.rs:1:18
+   |
+LL | fn thing(x: impl FnOnce(&u32)) {}
+   |                  ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 0af44d21196..02ba60f7f4b 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -26,37 +26,77 @@ error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(*mut &'r u32,)>`
               found type `Fn<(*mut &'a u32,)>`
+note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(*mut &u32,)>`
               found type `FnOnce<(*mut &'a u32,)>`
+note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(*mut &'r u32,)>`
               found type `Fn<(*mut &'a u32,)>`
+note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(*mut &u32,)>`
               found type `FnOnce<(*mut &'a u32,)>`
+note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
+  --> $DIR/closure-arg-type-mismatch.rs:9:10
+   |
+LL | fn _test<'a>(f: fn(*mut &'a u32)) {
+   |          ^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-arg-type-mismatch.rs:8:11
+   |
+LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
+   |           ^^^^^^^^^^^^^
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index 149f505dc6f..c41bece3c19 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -2,10 +2,20 @@ error[E0308]: mismatched types
   --> $DIR/closure-mismatch.rs:8:5
    |
 LL |     baz(|_| ());
-   |     ^^^ one type is more general than the other
+   |     ^^^ lifetime mismatch
    |
    = note: expected type `for<'r> Fn<(&'r (),)>`
               found type `Fn<(&(),)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/closure-mismatch.rs:8:9
+   |
+LL |     baz(|_| ());
+   |         ^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/closure-mismatch.rs:5:11
+   |
+LL | fn baz<T: Foo>(_: T) {}
+   |           ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
index 790aea87510..be1dd1a8524 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
@@ -18,6 +18,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'static X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -27,6 +32,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'static X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
index 5e2a8db0286..9d9293e958e 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
@@ -6,6 +6,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -15,6 +20,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -24,6 +34,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -33,6 +48,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
               found type `Fn<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -42,6 +62,11 @@ LL |     type Bar = impl Baz<Self, Self>;
    |
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&'<empty> X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:25:9
+   |
+LL |         |x| x
+   |         ^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.stderr
index 5f343ff74a1..ecf3a96b5a8 100644
--- a/src/test/ui/unboxed-closures/issue-30906.stderr
+++ b/src/test/ui/unboxed-closures/issue-30906.stderr
@@ -2,10 +2,15 @@ error[E0308]: mismatched types
   --> $DIR/issue-30906.rs:15:5
    |
 LL |     test(Compose(f, |_| {}));
-   |     ^^^^ one type is more general than the other
+   |     ^^^^ lifetime mismatch
    |
    = note: expected type `FnOnce<(&'x str,)>`
               found type `FnOnce<(&str,)>`
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-30906.rs:3:12
+   |
+LL | fn test<F: for<'x> FnOnce<(&'x str,)>>(_: F) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error