about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-12-01 00:10:13 -0800
committerEsteban Küber <esteban@kuber.com.ar>2021-01-12 13:53:13 -0800
commita8a974245e239c995166e33f37fe6504fc8795c1 (patch)
tree8fcffe590b3446809c010e72107937500f94c104
parent704e47f78b4c8801a3c76f235a5a152e1b60b300 (diff)
downloadrust-a8a974245e239c995166e33f37fe6504fc8795c1.tar.gz
rust-a8a974245e239c995166e33f37fe6504fc8795c1.zip
Provide more information for HRTB lifetime errors involving closures
-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--src/test/ui/associated-types/higher-ranked-projection.bad.stderr7
-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
18 files changed, 392 insertions, 25 deletions
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/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/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