about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2020-05-18 09:43:36 +0000
committerNiko Matsakis <niko@alum.mit.edu>2020-06-22 14:05:00 +0000
commitbcc0a9c8eba0c4eaaafb7983b1b367a926ca8948 (patch)
tree98cd4d5a3ed85a1f4f036fb26788d172b3409e31 /src
parent1a4e2b6f9c75a0e21722c88a0e3b610d6ffc3ae3 (diff)
downloadrust-bcc0a9c8eba0c4eaaafb7983b1b367a926ca8948.tar.gz
rust-bcc0a9c8eba0c4eaaafb7983b1b367a926ca8948.zip
modify leak-check to track only outgoing edges from placeholders
Also, update the affected tests. This seems strictly better but it is
actually more permissive than I initially intended. In particular it
accepts this

```
forall<'a, 'b> {
  exists<'intersection> {
    'a: 'intersection,
    'b: 'intersection,
  }
}
```

and I'm not sure I want to accept that. It implies that we have a
`'empty` in the new universe intoduced by the `forall`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_infer/infer/region_constraints/leak_check.rs21
-rw-r--r--src/test/ui/closure-expected-type/expect-fn-supply-fn.rs6
-rw-r--r--src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr51
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr23
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr2
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr23
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr23
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr23
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr4
-rw-r--r--src/test/ui/hr-subtype/hr-subtype.rs8
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.stderr4
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs2
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr18
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr19
-rw-r--r--src/test/ui/hrtb/hrtb-just-for-static.stderr20
-rw-r--r--src/test/ui/hrtb/issue-46989.rs2
-rw-r--r--src/test/ui/hrtb/issue-46989.stderr19
-rw-r--r--src/test/ui/issues/issue-57362-1.rs2
-rw-r--r--src/test/ui/issues/issue-57362-1.stderr21
-rw-r--r--src/test/ui/issues/issue-57362-2.rs4
-rw-r--r--src/test/ui/issues/issue-57362-2.stderr39
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr.rs35
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr.stderr10
-rw-r--r--src/test/ui/regions-fn-subtyping-return-static-fail.stderr4
-rw-r--r--src/test/ui/where-clauses/where-for-self-2.rs2
-rw-r--r--src/test/ui/where-clauses/where-for-self-2.stderr19
30 files changed, 219 insertions, 201 deletions
diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs
index 91c39a0e78f..111a7b997a4 100644
--- a/src/librustc_infer/infer/region_constraints/leak_check.rs
+++ b/src/librustc_infer/infer/region_constraints/leak_check.rs
@@ -42,10 +42,23 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
                 _ => bug!("leak_check: expected placeholder found {:?}", placeholder_region,),
             };
 
-            // Find all regions that are related to this placeholder
-            // in some way. This means any region that either outlives
-            // or is outlived by a placeholder.
-            let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region);
+            // Find all regions that this placeholder `!p` must outlive -- i.e.,
+            // any region `r` where `!p: r` must hold. It is an error if any
+            // such region `r` is another placeholder or in a universe that
+            // can't see the placeholder. (This is actually incorrect, because
+            // we don't take into account the possibility of bounds in
+            // environment that tell us that the placeholder may be related to
+            // other regions).
+            //
+            // Note that we *don't* look for cases like `r: !p`. This is
+            // because:
+            //
+            // * If `r` is some other placeholder `!p1`, then we'll find the
+            //   error when we search the regions that `!p1` must outlive.
+            // * If `r` is a variable in some outer universe, then it can
+            //   potentially be assigned to `'static`, so this relation could
+            //   hold.
+            let mut taint_set = TaintSet::new(TaintDirections::outgoing(), placeholder_region);
             taint_set.fixed_point(
                 tcx,
                 self.undo_log.region_constraints(),
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
index a4e43da91ba..6977fd47a2e 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
@@ -28,14 +28,14 @@ fn expect_free_supply_bound() {
     // Here, we are given a function whose region is bound at closure level,
     // but we expect one bound in the argument. Error results.
     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
-    //~^ ERROR type mismatch
+    //~^ ERROR mismatched types
 }
 
 fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
     // Here, we are given a `fn(&u32)` but we expect a `fn(&'x
     // u32)`. In principle, this could be ok, but we demand equality.
     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
-    //~^ ERROR type mismatch
+    //~^ ERROR mismatched types
 }
 
 fn expect_bound_supply_free_from_closure() {
@@ -44,7 +44,7 @@ fn expect_bound_supply_free_from_closure() {
     // the argument level.
     type Foo<'a> = fn(&'a u32);
     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
-    //~^ ERROR type mismatch
+    //~^ ERROR mismatched types
     });
 }
 
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
index fae41c4114a..8a183bb704b 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -36,46 +36,33 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b
 LL |     with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
    |                                                ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/expect-fn-supply-fn.rs:30:5
+error[E0308]: mismatched types
+  --> $DIR/expect-fn-supply-fn.rs:30:52
    |
-LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
-   |    ------------------------------------------ required by a bound in this
-LL |     where F: for<'a> FnOnce(fn(&'a u32), &i32)
-   |                      ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region`
-...
 LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(fn(&'a u32), &i32) -> _`
+   |                                                    ^^^^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `fn(&u32)`
+              found fn pointer `for<'r> fn(&'r u32)`
 
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/expect-fn-supply-fn.rs:37:5
+error[E0308]: mismatched types
+  --> $DIR/expect-fn-supply-fn.rs:37:53
    |
-LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
-   |    ------------------------------------------- required by a bound in this
-LL |     where F: FnOnce(fn(&u32), &i32)
-   |              ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
-...
 LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
+   |                                                     ^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'r> fn(&'r u32)`
+              found fn pointer `fn(&'x u32)`
 
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/expect-fn-supply-fn.rs:46:5
+error[E0308]: mismatched types
+  --> $DIR/expect-fn-supply-fn.rs:46:53
    |
-LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
-   |    ------------------------------------------- required by a bound in this
-LL |     where F: FnOnce(fn(&u32), &i32)
-   |              ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
-...
 LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
-   |     |
-   |     expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
+   |                                                     ^^^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'r> fn(&'r u32)`
+              found fn pointer `fn(&u32)`
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0308, E0631.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
index 45f53d4fe99..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr
@@ -1,17 +1,14 @@
-error[E0308]: mismatched types
-  --> $DIR/hr-subtype.rs:39:26
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/hr-subtype.rs:96:1
    |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
-...
-LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
-LL | |                                 for<'a>    fn(&'a u32, &'a u32)) }
-   | |__________________________________________________________________- in this macro invocation
-   |
-   = note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>`
-              found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32)>`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
index 6aba6466fad..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr
@@ -1,11 +1,11 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/hr-subtype.rs:100:1
+  --> $DIR/hr-subtype.rs:96:1
    |
 LL | / fn main() {
 LL | |
 LL | |
 LL | |
-LL | |
+...  |
 LL | |
 LL | | }
    | |_^
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
index 6aba6466fad..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr
@@ -1,11 +1,11 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/hr-subtype.rs:100:1
+  --> $DIR/hr-subtype.rs:96:1
    |
 LL | / fn main() {
 LL | |
 LL | |
 LL | |
-LL | |
+...  |
 LL | |
 LL | | }
    | |_^
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
index c3e4f6d2ed0..b3e3f5dc401 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/hr-subtype.rs:39:26
    |
 LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
+   |                            ^^^^^^^^^^^ one type is more general than the other
 ...
 LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
 LL | |                              fn(&'x u32)) }
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
index 4d7b86027f5..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr
@@ -1,17 +1,14 @@
-error[E0308]: mismatched types
-  --> $DIR/hr-subtype.rs:39:26
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/hr-subtype.rs:96:1
    |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
-...
-LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
-LL | |                                       for<'a>    fn(Co<'a>, Co<'a>)) }
-   | |______________________________________________________________________- in this macro invocation
-   |
-   = note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>`
-              found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
index 7f0a4197dd7..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr
@@ -1,17 +1,14 @@
-error[E0308]: mismatched types
-  --> $DIR/hr-subtype.rs:39:26
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/hr-subtype.rs:96:1
    |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
-...
-LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
-LL | |                                         for<'a>    fn(Co<'a>, Co<'a>) -> Contra<'a>) }
-   | |______________________________________________________________________________________- in this macro invocation
-   |
-   = note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>`
-              found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
index 6aba6466fad..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr
@@ -1,11 +1,11 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/hr-subtype.rs:100:1
+  --> $DIR/hr-subtype.rs:96:1
    |
 LL | / fn main() {
 LL | |
 LL | |
 LL | |
-LL | |
+...  |
 LL | |
 LL | | }
    | |_^
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
index c12e543a44e..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr
@@ -1,17 +1,14 @@
-error[E0308]: mismatched types
-  --> $DIR/hr-subtype.rs:39:26
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/hr-subtype.rs:96:1
    |
-LL |               gimme::<$t1>(None::<$t2>);
-   |                            ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
-...
-LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
-LL | |                                             for<'a>    fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
-   | |______________________________________________________________________________________________- in this macro invocation
-   |
-   = note: expected enum `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>`
-              found enum `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+LL | / fn main() {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
index 6aba6466fad..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr
@@ -1,11 +1,11 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/hr-subtype.rs:100:1
+  --> $DIR/hr-subtype.rs:96:1
    |
 LL | / fn main() {
 LL | |
 LL | |
 LL | |
-LL | |
+...  |
 LL | |
 LL | | }
    | |_^
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
index 6aba6466fad..c4e838e6887 100644
--- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
+++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr
@@ -1,11 +1,11 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/hr-subtype.rs:100:1
+  --> $DIR/hr-subtype.rs:96:1
    |
 LL | / fn main() {
 LL | |
 LL | |
 LL | |
-LL | |
+...  |
 LL | |
 LL | | }
    | |_^
diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs
index b31f198bd97..995ec64d53b 100644
--- a/src/test/ui/hr-subtype/hr-subtype.rs
+++ b/src/test/ui/hr-subtype/hr-subtype.rs
@@ -42,10 +42,6 @@ macro_rules! check {
             //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR
             //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
             //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
-            //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
-            //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
-            //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
-            //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
         }
     }
 }
@@ -103,4 +99,8 @@ fn main() {
 //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
 //[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
 //[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
+//[bound_a_b_vs_bound_a]~^^^^^^ ERROR fatal error triggered by #[rustc_error]
+//[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR fatal error triggered by #[rustc_error]
+//[bound_co_a_co_b_ret_contra_a]~^^^^^^^^ ERROR fatal error triggered by #[rustc_error]
+//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR fatal error triggered by #[rustc_error]
 }
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
index 328e98657ef..9914783d976 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
@@ -2,9 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/hrtb-exists-forall-fn.rs:17:34
    |
 LL |     let _: for<'b> fn(&'b u32) = foo();
-   |            -------------------   ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b
-   |            |
-   |            expected due to this
+   |                                  ^^^^^ one type is more general than the other
    |
    = note: expected fn pointer `for<'b> fn(&'b u32)`
               found fn pointer `fn(&u32)`
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
index 4c1d4d28a09..921061916fc 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
@@ -32,5 +32,5 @@ fn main() {
     // NB. *However*, the reinstated leak-check gives an error here.
 
     foo::<()>();
-    //~^ ERROR not satisfied
+    //~^ ERROR implementation of `Trait` is not general enough
 }
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
index 7a7285d3d76..fe8209d054c 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr
@@ -1,18 +1,14 @@
-error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
-  --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11
+error: implementation of `Trait` is not general enough
+  --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
    |
-LL | fn foo<T>()
-   |    --- required by a bound in this
-LL | where
-LL |     T: Trait<for<'b> fn(&'b u32)>,
-   |        -------------------------- required by this bound in `foo`
+LL | trait Trait<T> {}
+   | ----------------- trait `Trait` defined here
 ...
 LL |     foo::<()>();
-   |           ^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
+   |     ^^^^^^^^^ implementation of `Trait` is not general enough
    |
-   = help: the following implementations were found:
-             <() as Trait<fn(&'a u32)>>
+   = note: `()` must implement `Trait<for<'b> fn(&'b u32)>`
+   = note: ...but `()` actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
index 87a13889298..ebb3abf1848 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -1,19 +1,12 @@
-error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
-  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
+error[E0308]: mismatched types
+  --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5
    |
-LL | fn want_bar_for_any_ccx<B>(b: &B)
-   |    -------------------- required by a bound in this
-LL |     where B : for<'ccx> Bar<'ccx>
-   |               ------------------- required by this bound in `want_bar_for_any_ccx`
-...
 LL |     want_bar_for_any_ccx(b);
-   |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
-help: consider further restricting this bound
-   |
-LL |     where B : Qux + for<'ccx> Bar<'ccx>
-   |                   ^^^^^^^^^^^^^^^^^^^^^
+   = note: expected type `for<'ccx> Bar<'ccx>`
+              found type `Bar<'static>`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr
index 4fa40462477..bf7373059a0 100644
--- a/src/test/ui/hrtb/hrtb-just-for-static.stderr
+++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr
@@ -1,16 +1,16 @@
-error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied
-  --> $DIR/hrtb-just-for-static.rs:24:17
+error: implementation of `Foo` is not general enough
+  --> $DIR/hrtb-just-for-static.rs:24:5
    |
-LL | fn want_hrtb<T>()
-   |    --------- required by a bound in this
-LL |     where T : for<'a> Foo<&'a isize>
-   |               ---------------------- required by this bound in `want_hrtb`
+LL | / trait Foo<X> {
+LL | |     fn foo(&self, x: X) { }
+LL | | }
+   | |_- trait `Foo` defined here
 ...
-LL |     want_hrtb::<StaticInt>()
-   |                 ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
+LL |       want_hrtb::<StaticInt>()
+   |       ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = help: the following implementations were found:
-             <StaticInt as Foo<&'static isize>>
+   = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
+   = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1`
 
 error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied
   --> $DIR/hrtb-just-for-static.rs:30:17
diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs
index 2c859055458..eb6549099fe 100644
--- a/src/test/ui/hrtb/issue-46989.rs
+++ b/src/test/ui/hrtb/issue-46989.rs
@@ -38,5 +38,5 @@ fn assert_foo<T: Foo>() {}
 
 fn main() {
     assert_foo::<fn(&i32)>();
-    //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
+    //~^ ERROR implementation of `Foo` is not general enough
 }
diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr
index 0a7382c4dd8..0865aa4224b 100644
--- a/src/test/ui/hrtb/issue-46989.stderr
+++ b/src/test/ui/hrtb/issue-46989.stderr
@@ -1,15 +1,16 @@
-error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
-  --> $DIR/issue-46989.rs:40:18
+error: implementation of `Foo` is not general enough
+  --> $DIR/issue-46989.rs:40:5
    |
-LL | fn assert_foo<T: Foo>() {}
-   |                  --- required by this bound in `assert_foo`
+LL | / trait Foo {
+LL | |
+LL | | }
+   | |_- trait `Foo` defined here
 ...
-LL |     assert_foo::<fn(&i32)>();
-   |                  ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)`
+LL |       assert_foo::<fn(&i32)>();
+   |       ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
-   = help: the following implementations were found:
-             <fn(A) as Foo>
+   = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)`
+   = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs
index 1fa417fe98a..3ba82300fab 100644
--- a/src/test/ui/issues/issue-57362-1.rs
+++ b/src/test/ui/issues/issue-57362-1.rs
@@ -17,7 +17,7 @@ impl<T> Trait for fn(&T) {
 
 fn f() {
     let a: fn(_) = |_: &u8| {};
-    a.f(); //~ ERROR no method named `f`
+    a.f(); //~ ERROR implementation of `Trait` is not general enough
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr
index 5c611cd43d3..24408420b13 100644
--- a/src/test/ui/issues/issue-57362-1.stderr
+++ b/src/test/ui/issues/issue-57362-1.stderr
@@ -1,17 +1,16 @@
-error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope
+error: implementation of `Trait` is not general enough
   --> $DIR/issue-57362-1.rs:20:7
    |
-LL |     a.f();
-   |       ^ method not found in `fn(&u8)`
+LL | / trait Trait {
+LL | |     fn f(self);
+LL | | }
+   | |_- trait `Trait` defined here
+...
+LL |       a.f();
+   |         ^ implementation of `Trait` is not general enough
    |
-   = note: `a` is a function, perhaps you wish to call it
-   = help: items from traits can only be used if the trait is implemented and in scope
-note: `Trait` defines an item `f`, perhaps you need to implement it
-  --> $DIR/issue-57362-1.rs:8:1
-   |
-LL | trait Trait {
-   | ^^^^^^^^^^^
+   = note: `Trait` would have to be implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`...
+   = note: ...but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs
index 870d7f28ba9..7b6594abc96 100644
--- a/src/test/ui/issues/issue-57362-2.rs
+++ b/src/test/ui/issues/issue-57362-2.rs
@@ -19,7 +19,9 @@ impl<'a> X for fn(&'a ()) {
 }
 
 fn g() {
-    let x = <fn (&())>::make_g(); //~ ERROR no function or associated item
+    let x = <fn (&())>::make_g();
+    //~^ ERROR implementation of `X` is not general enough
+    //~| ERROR implementation of `X` is not general enough
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
index 2edc0097464..dfd48ec2227 100644
--- a/src/test/ui/issues/issue-57362-2.stderr
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -1,16 +1,33 @@
-error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope
-  --> $DIR/issue-57362-2.rs:22:25
+error: implementation of `X` is not general enough
+  --> $DIR/issue-57362-2.rs:22:13
    |
-LL |     let x = <fn (&())>::make_g();
-   |                         ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())`
+LL | / trait X {
+LL | |     type G;
+LL | |     fn make_g() -> Self::G;
+LL | | }
+   | |_- trait `X` defined here
+...
+LL |       let x = <fn (&())>::make_g();
+   |               ^^^^^^^^^^^^^^^^^^ implementation of `X` is not general enough
    |
-   = help: items from traits can only be used if the trait is implemented and in scope
-note: `X` defines an item `make_g`, perhaps you need to implement it
-  --> $DIR/issue-57362-2.rs:8:1
+   = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())`
+   = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
+
+error: implementation of `X` is not general enough
+  --> $DIR/issue-57362-2.rs:22:13
+   |
+LL | / trait X {
+LL | |     type G;
+LL | |     fn make_g() -> Self::G;
+   | |     ----------------------- due to a where-clause on `X::make_g`...
+LL | | }
+   | |_- trait `X` defined here
+...
+LL |       let x = <fn (&())>::make_g();
+   |               ^^^^^^^^^^^^^^^^^^ doesn't satisfy where-clause
    |
-LL | trait X {
-   | ^^^^^^^
+   = note: ...`X` would have to be implemented for the type `for<'r> fn(&'r ())`
+   = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs
index bc7b787cd65..5e24a99bcc3 100644
--- a/src/test/ui/lub-glb/old-lub-glb-hr.rs
+++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs
@@ -3,21 +3,21 @@
 // error. However, now that we handle subtyping correctly, we no
 // longer get an error, because we recognize these two types as
 // equivalent!
-//
-// Whoops -- now that we reinstituted the leak-check, we get an error
-// again.
 
 fn foo(
     x: fn(&u8, &u8),
     y: for<'a> fn(&'a u8, &'a u8),
 ) {
+    // The two types above are actually equivalent. With the older
+    // leak check, though, we didn't consider them as equivalent, and
+    // hence we gave errors. But now we've fixed that.
     let z = match 22 {
         0 => x,
-        _ => y, //~ ERROR `match` arms have incompatible types
+        _ => y,
     };
 }
 
-fn bar(
+fn foo_cast(
     x: fn(&u8, &u8),
     y: for<'a> fn(&'a u8, &'a u8),
 ) {
@@ -28,5 +28,30 @@ fn bar(
     };
 }
 
+fn bar(
+    x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8,
+    y: for<'a> fn(&'a u8, &'a u8) -> &'a u8,
+) {
+    // The two types above are not equivalent. With the older LUB/GLB
+    // algorithm, this may have worked (I don't remember), but now it
+    // doesn't because we require equality.
+    let z = match 22 {
+        0 => x,
+        _ => y, //~ ERROR `match` arms have incompatible types
+    };
+}
+
+fn bar_cast(
+    x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8,
+    y: for<'a> fn(&'a u8, &'a u8) -> &'a u8,
+) {
+    // But we can *upcast* explicitly the type of `x` and figure
+    // things out:
+    let z = match 22 {
+        0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
+        _ => y,
+    };
+}
+
 fn main() {
 }
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
index 6d5d5117469..d242fb7789a 100644
--- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr
+++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr
@@ -1,17 +1,17 @@
 error[E0308]: `match` arms have incompatible types
-  --> $DIR/old-lub-glb-hr.rs:16:14
+  --> $DIR/old-lub-glb-hr.rs:40:14
    |
 LL |       let z = match 22 {
    |  _____________-
 LL | |         0 => x,
-   | |              - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)`
+   | |              - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
 LL | |         _ => y,
-   | |              ^ expected bound lifetime parameter, found concrete lifetime
+   | |              ^ expected bound lifetime parameter 'a, found concrete lifetime
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
-   = note:    expected type `for<'r, 's> fn(&'r u8, &'s u8)`
-           found fn pointer `for<'a> fn(&'a u8, &'a u8)`
+   = note:    expected type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+           found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr
index 27704b3e0a8..7848f770a70 100644
--- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr
+++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr
@@ -11,10 +11,10 @@ error[E0308]: mismatched types
   --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12
    |
 LL |     want_G(baz);
-   |            ^^^ expected concrete lifetime, found bound lifetime parameter 'cx
+   |            ^^^ one type is more general than the other
    |
    = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
-                 found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
+              found fn pointer `for<'r> fn(&'r S) -> &'r S`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs
index 31174fd4cf1..0ce38e69f6b 100644
--- a/src/test/ui/where-clauses/where-for-self-2.rs
+++ b/src/test/ui/where-clauses/where-for-self-2.rs
@@ -18,5 +18,5 @@ fn foo<T>(x: &T)
 {}
 
 fn main() {
-    foo(&X); //~ ERROR trait bound
+    foo(&X); //~ ERROR implementation of `Bar` is not general enough
 }
diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr
index 9976243b200..b3cadf5b1b0 100644
--- a/src/test/ui/where-clauses/where-for-self-2.stderr
+++ b/src/test/ui/where-clauses/where-for-self-2.stderr
@@ -1,17 +1,16 @@
-error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied
+error: implementation of `Bar` is not general enough
   --> $DIR/where-for-self-2.rs:21:5
    |
-LL | fn foo<T>(x: &T)
-   |    --- required by a bound in this
-LL |     where for<'a> &'a T: Bar
-   |                          --- required by this bound in `foo`
+LL | / trait Bar {
+LL | |     fn bar(&self);
+LL | | }
+   | |_- trait `Bar` defined here
 ...
-LL |     foo(&X);
-   |     ^^^ the trait `for<'a> Bar` is not implemented for `&'a _`
+LL |       foo(&X);
+   |       ^^^ implementation of `Bar` is not general enough
    |
-   = help: the following implementations were found:
-             <&'static u32 as Bar>
+   = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
+   = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.