about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2021-02-09 22:59:32 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2021-02-09 22:59:32 +0000
commit94c11dfe78c9c2e81ababe51b04231db4c90d07f (patch)
tree40c18db2ffd3f930109e7219e5965730736cf5cf
parentdaab6db1a02b680a71976fcbeed577ff102b31e4 (diff)
downloadrust-94c11dfe78c9c2e81ababe51b04231db4c90d07f.tar.gz
rust-94c11dfe78c9c2e81ababe51b04231db4c90d07f.zip
Report "nice" placeholder errors more often
If we have a cause containing `ValuePairs::PolyTraitRefs` but neither
TraitRef has any escaping bound regions then we report the same error as
for `ValuePairs::TraitRefs`.
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs142
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr38
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.rs39
-rw-r--r--src/test/ui/hrtb/hrtb-perfect-forwarding.stderr41
-rw-r--r--src/test/ui/issues/issue-57843.nll.stderr2
-rw-r--r--src/test/ui/issues/issue-57843.rs6
-rw-r--r--src/test/ui/issues/issue-57843.stderr16
-rw-r--r--src/test/ui/lifetimes/issue-79187.rs2
-rw-r--r--src/test/ui/lifetimes/issue-79187.stderr19
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.rs4
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr36
-rw-r--r--src/test/ui/rfc1623.rs2
-rw-r--r--src/test/ui/rfc1623.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr13
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr39
-rw-r--r--src/test/ui/unboxed-closures/issue-30906.nll.stderr2
-rw-r--r--src/test/ui/unboxed-closures/issue-30906.rs12
-rw-r--r--src/test/ui/unboxed-closures/issue-30906.stderr16
19 files changed, 181 insertions, 263 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 09be0b07670..285666b7acb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -30,157 +30,153 @@ impl NiceRegionError<'me, 'tcx> {
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 Some(sub_placeholder),
                 Some(sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 _,
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 Some(sub_placeholder),
                 None,
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 _,
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
                 _,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::UpperBoundUniverseConflict(
                 vid,
                 _,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region @ ty::RePlaceholder(_),
                 sup_region @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 None,
                 cause,
                 Some(*sub_region),
                 Some(*sup_region),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region @ ty::RePlaceholder(_),
                 sup_region,
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(sup_region),
                 cause,
                 Some(*sub_region),
                 None,
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region,
                 sup_region @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(sub_region),
                 cause,
                 None,
                 Some(*sup_region),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             _ => None,
         }
     }
 
+    fn try_report_trait_placeholder_mismatch(
+        &self,
+        vid: Option<ty::Region<'tcx>>,
+        cause: &ObligationCause<'tcx>,
+        sub_placeholder: Option<ty::Region<'tcx>>,
+        sup_placeholder: Option<ty::Region<'tcx>>,
+        value_pairs: &ValuePairs<'tcx>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        let (expected_substs, found_substs, trait_def_id) = match value_pairs {
+            ValuePairs::TraitRefs(ExpectedFound { expected, found })
+                if expected.def_id == found.def_id =>
+            {
+                (expected.substs, found.substs, expected.def_id)
+            }
+            ValuePairs::PolyTraitRefs(ExpectedFound { expected, found })
+                if expected.def_id() == found.def_id() =>
+            {
+                // It's possible that the placeholders come from a binder
+                // outside of this value pair. Use `no_bound_vars` as a
+                // simple heuristic for that.
+                (expected.no_bound_vars()?.substs, found.no_bound_vars()?.substs, expected.def_id())
+            }
+            _ => return None,
+        };
+
+        Some(self.report_trait_placeholder_mismatch(
+            vid,
+            cause,
+            sub_placeholder,
+            sup_placeholder,
+            trait_def_id,
+            expected_substs,
+            found_substs,
+        ))
+    }
+
     // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
     //   --> /home/nmatsakis/tmp/foo.rs:12:5
     //    |
@@ -191,7 +187,7 @@ impl NiceRegionError<'me, 'tcx> {
     //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
     //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
     #[instrument(level = "debug", skip(self))]
-    fn try_report_placeholders_trait(
+    fn report_trait_placeholder_mismatch(
         &self,
         vid: Option<ty::Region<'tcx>>,
         cause: &ObligationCause<'tcx>,
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
index edce0e6702e..c3dd7949575 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr
@@ -1,11 +1,11 @@
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:22:1
+  --> $DIR/hrtb-perfect-forwarding.rs:16:1
    |
-LL | / fn no_hrtb<'b,T>(mut t: T)
-LL | |     where T : Bar<&'b isize>
+LL | / fn no_hrtb<'b, T>(mut t: T)
+LL | | where
+LL | |     T: Bar<&'b isize>,
 LL | | {
-LL | |     // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that
-LL | |     // `&mut T : Bar<&'b isize>`.
+...  |
 LL | |     no_hrtb(&mut t);
    | |     --------------- recursive call site
 LL | | }
@@ -15,12 +15,12 @@ LL | | }
    = help: a `loop` may express intention better if this is on purpose
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:30:1
+  --> $DIR/hrtb-perfect-forwarding.rs:25:1
    |
 LL | / fn bar_hrtb<T>(mut t: T)
-LL | |     where T : for<'b> Bar<&'b isize>
+LL | | where
+LL | |     T: for<'b> Bar<&'b isize>,
 LL | | {
-LL | |     // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above
 ...  |
 LL | |     bar_hrtb(&mut t);
    | |     ---------------- recursive call site
@@ -30,25 +30,26 @@ LL | | }
    = help: a `loop` may express intention better if this is on purpose
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:39:1
+  --> $DIR/hrtb-perfect-forwarding.rs:35:1
    |
-LL | / fn foo_hrtb_bar_not<'b,T>(mut t: T)
-LL | |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T)
+LL | | where
+LL | |     T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
 LL | | {
-LL | |     // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
 ...  |
 LL | |     foo_hrtb_bar_not(&mut t);
    | |     ------------------------ recursive call site
 LL | |
+LL | |
 LL | | }
    | |_^ cannot return without recursing
    |
    = help: a `loop` may express intention better if this is on purpose
 
 error: lifetime may not live long enough
-  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+  --> $DIR/hrtb-perfect-forwarding.rs:43:5
    |
-LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
+LL | fn foo_hrtb_bar_not<'b, T>(mut t: T)
    |                     -- lifetime `'b` defined here
 ...
 LL |     foo_hrtb_bar_not(&mut t);
@@ -57,18 +58,19 @@ LL |     foo_hrtb_bar_not(&mut t);
    = help: consider replacing `'b` with `'static`
 
 error: higher-ranked subtype error
-  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+  --> $DIR/hrtb-perfect-forwarding.rs:43:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-perfect-forwarding.rs:50:1
+  --> $DIR/hrtb-perfect-forwarding.rs:48:1
    |
 LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T)
-LL | |     where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
+LL | | where
+LL | |     T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
 LL | | {
-LL | |     // OK -- now we have `T : for<'b> Bar&'b isize>`.
+LL | |     // OK -- now we have `T : for<'b> Bar<&'b isize>`.
 LL | |     foo_hrtb_bar_hrtb(&mut t);
    | |     ------------------------- recursive call site
 LL | | }
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
index 0303a764c12..441a788359e 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs
@@ -2,25 +2,20 @@
 // is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
 
 trait Foo<X> {
-    fn foo(&mut self, x: X) { }
+    fn foo(&mut self, x: X) {}
 }
 
 trait Bar<X> {
-    fn bar(&mut self, x: X) { }
+    fn bar(&mut self, x: X) {}
 }
 
-impl<'a,X,F> Foo<X> for &'a mut F
-    where F : Foo<X> + Bar<X>
-{
-}
+impl<'a, X, F> Foo<X> for &'a mut F where F: Foo<X> + Bar<X> {}
 
-impl<'a,X,F> Bar<X> for &'a mut F
-    where F : Bar<X>
-{
-}
+impl<'a, X, F> Bar<X> for &'a mut F where F: Bar<X> {}
 
-fn no_hrtb<'b,T>(mut t: T)
-    where T : Bar<&'b isize>
+fn no_hrtb<'b, T>(mut t: T)
+where
+    T: Bar<&'b isize>,
 {
     // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that
     // `&mut T : Bar<&'b isize>`.
@@ -28,7 +23,8 @@ fn no_hrtb<'b,T>(mut t: T)
 }
 
 fn bar_hrtb<T>(mut t: T)
-    where T : for<'b> Bar<&'b isize>
+where
+    T: for<'b> Bar<&'b isize>,
 {
     // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above
     // ensures that `&mut T : for<'b> Bar<&'b isize>`.  This is an
@@ -36,22 +32,25 @@ fn bar_hrtb<T>(mut t: T)
     bar_hrtb(&mut t);
 }
 
-fn foo_hrtb_bar_not<'b,T>(mut t: T)
-    where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
+fn foo_hrtb_bar_not<'b, T>(mut t: T)
+where
+    T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
 {
     // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
     // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
     // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
     // clause only specifies `T : Bar<&'b isize>`.
-    foo_hrtb_bar_not(&mut t); //~ ERROR mismatched types
-                              //~| ERROR mismatched types
+    foo_hrtb_bar_not(&mut t);
+    //~^ ERROR implementation of `Bar` is not general enough
+    //~| ERROR implementation of `Bar` is not general enough
 }
 
 fn foo_hrtb_bar_hrtb<T>(mut t: T)
-    where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>
+where
+    T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>,
 {
-    // OK -- now we have `T : for<'b> Bar&'b isize>`.
+    // OK -- now we have `T : for<'b> Bar<&'b isize>`.
     foo_hrtb_bar_hrtb(&mut t);
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
index ed810d443be..e265f53cd2a 100644
--- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr
@@ -1,41 +1,20 @@
-error[E0308]: mismatched types
-  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+error: implementation of `Bar` is not general enough
+  --> $DIR/hrtb-perfect-forwarding.rs:43:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
-   |     ^^^^^^^^^^^^^^^^ lifetime mismatch
+   |     ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough
    |
-   = 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>
-   |               ^^^^^^^^^^^^^^^^^^^^^^
+   = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1`
 
-error[E0308]: mismatched types
-  --> $DIR/hrtb-perfect-forwarding.rs:46:5
+error: implementation of `Bar` is not general enough
+  --> $DIR/hrtb-perfect-forwarding.rs:43:5
    |
 LL |     foo_hrtb_bar_not(&mut t);
-   |     ^^^^^^^^^^^^^^^^ 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
+   |     ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough
    |
-LL |     where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
-   |               ^^^^^^^^^^^^^^^^^^^^^^
+   = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`...
+   = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1`
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57843.nll.stderr b/src/test/ui/issues/issue-57843.nll.stderr
index 70310780b43..70d16cc9a1d 100644
--- a/src/test/ui/issues/issue-57843.nll.stderr
+++ b/src/test/ui/issues/issue-57843.nll.stderr
@@ -1,5 +1,5 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57843.rs:23:9
+  --> $DIR/issue-57843.rs:25:9
    |
 LL |     Foo(Box::new(|_| ()));
    |         ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-57843.rs b/src/test/ui/issues/issue-57843.rs
index 46608255266..11629690ecc 100644
--- a/src/test/ui/issues/issue-57843.rs
+++ b/src/test/ui/issues/issue-57843.rs
@@ -11,7 +11,9 @@ trait ClonableFn<T> {
 }
 
 impl<T, F: 'static> ClonableFn<T> for F
-where F: Fn(T) + Clone {
+where
+    F: Fn(T) + Clone,
+{
     fn clone(&self) -> Box<dyn Fn(T)> {
         Box::new(self.clone())
     }
@@ -20,5 +22,5 @@ where F: Fn(T) + Clone {
 struct Foo(Box<dyn for<'a> ClonableFn<&'a bool>>);
 
 fn main() {
-    Foo(Box::new(|_| ())); //~ ERROR mismatched types
+    Foo(Box::new(|_| ())); //~ ERROR implementation of `FnOnce` is not general enough
 }
diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr
index 7699e97da99..acd48b6c7e5 100644
--- a/src/test/ui/issues/issue-57843.stderr
+++ b/src/test/ui/issues/issue-57843.stderr
@@ -1,17 +1,11 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-57843.rs:23:9
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-57843.rs:25:9
    |
 LL |     Foo(Box::new(|_| ()));
-   |         ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |         ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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(|_| ()));
-   |                  ^^^^^^
+   = note: `[closure@$DIR/issue-57843.rs:25:18: 25:24]` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/issue-79187.rs b/src/test/ui/lifetimes/issue-79187.rs
index bf331d8a606..2ee69ee2234 100644
--- a/src/test/ui/lifetimes/issue-79187.rs
+++ b/src/test/ui/lifetimes/issue-79187.rs
@@ -2,5 +2,5 @@ fn thing(x: impl FnOnce(&u32)) {}
 
 fn main() {
     let f = |_| ();
-    thing(f); //~ERROR mismatched types
+    thing(f); //~ERROR implementation of `FnOnce` is not general enough
 }
diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr
index 63f501e08fc..3627ab5ed1e 100644
--- a/src/test/ui/lifetimes/issue-79187.stderr
+++ b/src/test/ui/lifetimes/issue-79187.stderr
@@ -1,22 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-79187.rs:5:5
    |
 LL |     thing(f);
-   |     ^^^^^ lifetime mismatch
+   |     ^^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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)) {}
-   |                  ^^^^^^^^^^^^
+   = note: `[closure@$DIR/issue-79187.rs:4:13: 4:19]` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2`
 
 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.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
index e278049c8cc..2d485d14a8d 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
@@ -8,8 +8,8 @@ fn main() {
 fn baz<F: Fn(*mut &u32)>(_: F) {}
 fn _test<'a>(f: fn(*mut &'a u32)) {
     baz(f);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 }
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 02ba60f7f4b..67c5a68ed83 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -41,24 +41,14 @@ note: the lifetime requirement is introduced here
 LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
    |           ^^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ 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
+   |     ^^^ implementation of `FnOnce` is not general enough
    |
-LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
-   |           ^^^^^^^^^^^^^
+   = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2`
 
 error[E0308]: mismatched types
   --> $DIR/closure-arg-type-mismatch.rs:10:5
@@ -79,24 +69,14 @@ note: the lifetime requirement is introduced here
 LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
    |           ^^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/closure-arg-type-mismatch.rs:10:5
    |
 LL |     baz(f);
-   |     ^^^ 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
+   |     ^^^ implementation of `FnOnce` is not general enough
    |
-LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
-   |           ^^^^^^^^^^^^^
+   = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs
index aa6b1c0012c..9ff4813d112 100644
--- a/src/test/ui/rfc1623.rs
+++ b/src/test/ui/rfc1623.rs
@@ -22,7 +22,7 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct {
     foo: &Foo { bools: &[false, true] },
     bar: &Bar { bools: &[true, true] },
     f: &id,
-    //~^ ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
 };
 
 // very simple test for a 'static static with default lifetime
diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr
index 2835e47fa45..e95e68c8e6d 100644
--- a/src/test/ui/rfc1623.stderr
+++ b/src/test/ui/rfc1623.stderr
@@ -1,12 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/rfc1623.rs:24:8
    |
 LL |     f: &id,
-   |        ^^^ one type is more general than the other
+   |        ^^^ implementation of `FnOnce` is not general enough
    |
-   = note: expected type `FnOnce<(&'a Foo<'b>,)>`
-              found type `FnOnce<(&Foo<'_>,)>`
+   = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
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 be1dd1a8524..59b14eedc24 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
@@ -24,19 +24,14 @@ note: this closure does not fulfill the lifetime requirements
 LL |         |x| x
    |         ^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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
-   |         ^^^^^
+   = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
index 3372b81404e..561528c2abb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -15,9 +15,9 @@ struct X;
 
 impl Foo for X {
     type Bar = impl Baz<Self, Self>;
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
-    //~| ERROR mismatched types
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
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 9d9293e958e..59c91d52cca 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
@@ -1,16 +1,11 @@
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
-   |
-   = 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
+   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-LL |         |x| x
-   |         ^^^^^
+   = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -26,19 +21,14 @@ note: this closure does not fulfill the lifetime requirements
 LL |         |x| x
    |         ^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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
-   |         ^^^^^
+   = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
 error[E0308]: mismatched types
   --> $DIR/issue-57611-trait-alias.rs:17:16
@@ -54,19 +44,14 @@ note: this closure does not fulfill the lifetime requirements
 LL |         |x| x
    |         ^^^^^
 
-error[E0308]: mismatched types
+error: implementation of `FnOnce` is not general enough
   --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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
-   |         ^^^^^
+   = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/unboxed-closures/issue-30906.nll.stderr b/src/test/ui/unboxed-closures/issue-30906.nll.stderr
index 5a2cbab9a15..2db392e8b8b 100644
--- a/src/test/ui/unboxed-closures/issue-30906.nll.stderr
+++ b/src/test/ui/unboxed-closures/issue-30906.nll.stderr
@@ -1,5 +1,5 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-30906.rs:15:5
+  --> $DIR/issue-30906.rs:18:5
    |
 LL |     test(Compose(f, |_| {}));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/unboxed-closures/issue-30906.rs b/src/test/ui/unboxed-closures/issue-30906.rs
index 03cce832775..e2d219e4703 100644
--- a/src/test/ui/unboxed-closures/issue-30906.rs
+++ b/src/test/ui/unboxed-closures/issue-30906.rs
@@ -2,9 +2,12 @@
 
 fn test<F: for<'x> FnOnce<(&'x str,)>>(_: F) {}
 
-struct Compose<F,G>(F,G);
-impl<T,F,G> FnOnce<(T,)> for Compose<F,G>
-where F: FnOnce<(T,)>, G: FnOnce<(F::Output,)> {
+struct Compose<F, G>(F, G);
+impl<T, F, G> FnOnce<(T,)> for Compose<F, G>
+where
+    F: FnOnce<(T,)>,
+    G: FnOnce<(F::Output,)>,
+{
     type Output = G::Output;
     extern "rust-call" fn call_once(self, (x,): (T,)) -> G::Output {
         (self.1)((self.0)(x))
@@ -12,7 +15,8 @@ where F: FnOnce<(T,)>, G: FnOnce<(F::Output,)> {
 }
 
 fn bad<T>(f: fn(&'static str) -> T) {
-    test(Compose(f, |_| {})); //~ ERROR: mismatched types
+    test(Compose(f, |_| {}));
+    //~^ ERROR: implementation of `FnOnce` is not general enough
 }
 
 fn main() {}
diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.stderr
index ecf3a96b5a8..35b1e454c02 100644
--- a/src/test/ui/unboxed-closures/issue-30906.stderr
+++ b/src/test/ui/unboxed-closures/issue-30906.stderr
@@ -1,17 +1,11 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-30906.rs:15:5
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-30906.rs:18:5
    |
 LL |     test(Compose(f, |_| {}));
-   |     ^^^^ lifetime mismatch
+   |     ^^^^ implementation of `FnOnce` is not general enough
    |
-   = 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) {}
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.