about summary refs log tree commit diff
path: root/src/test/ui/impl-trait
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-02-14 16:10:22 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-28 16:27:14 +0000
commit264cd05b16198c2838ec6cd585bd122491e3f7a9 (patch)
tree133ca794d093e515a783cd92db831ff51e197820 /src/test/ui/impl-trait
parent0e4524e5b4a9c5656fef69f532f96eb9959a1803 (diff)
downloadrust-264cd05b16198c2838ec6cd585bd122491e3f7a9.tar.gz
rust-264cd05b16198c2838ec6cd585bd122491e3f7a9.zip
Revert "Auto merge of #93893 - oli-obk:sad_revert, r=oli-obk"
This reverts commit 6499c5e7fc173a3f55b7a3bd1e6a50e9edef782d, reversing
changes made to 78450d2d602b06d9b94349aaf8cece1a4acaf3a8.
Diffstat (limited to 'src/test/ui/impl-trait')
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs1
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr112
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs2
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr4
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.rs6
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.stderr24
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.stderr6
-rw-r--r--src/test/ui/impl-trait/equality.stderr14
-rw-r--r--src/test/ui/impl-trait/equality2.stderr4
-rw-r--r--src/test/ui/impl-trait/fallback.rs9
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.rs4
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.stderr16
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque-2.rs34
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr11
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque.rs32
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.rs7
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.stderr27
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.rs7
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.stderr20
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.rs20
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.stderr9
-rw-r--r--src/test/ui/impl-trait/issue-55872.rs2
-rw-r--r--src/test/ui/impl-trait/issue-55872.stderr10
-rw-r--r--src/test/ui/impl-trait/issue-72911.rs2
-rw-r--r--src/test/ui/impl-trait/issue-72911.stderr22
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.rs6
-rw-r--r--src/test/ui/impl-trait/issues/issue-70877.stderr40
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.rs5
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.stderr35
-rw-r--r--src/test/ui/impl-trait/issues/issue-86201.rs4
-rw-r--r--src/test/ui/impl-trait/issues/issue-86201.stderr21
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr51
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.rs23
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.stderr20
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.rs19
-rw-r--r--src/test/ui/impl-trait/lifetimes2.rs10
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr9
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr9
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr9
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr22
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs4
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr49
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs2
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr6
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.rs2
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.stderr38
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr37
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs12
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr190
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs2
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr8
-rw-r--r--src/test/ui/impl-trait/question_mark.rs13
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs3
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr12
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs2
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs29
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr18
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs37
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound.rs2
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound.stderr9
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.rs4
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr32
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other.rs19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other.stderr19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other2.rs16
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other2.stderr19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other3.rs19
-rw-r--r--src/test/ui/impl-trait/two_tait_defining_each_other3.stderr19
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.nll.stderr6
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.rs2
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.stderr8
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.rs7
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.stderr13
76 files changed, 848 insertions, 504 deletions
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index c2fbbf94fd6..d2452abab02 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -11,6 +11,7 @@ fn main() {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
+    //~| ERROR cycle detected
     send(cycle2().clone());
 
     Rc::new(Cell::new(5))
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 634ff14869e..14db864f1c2 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -30,47 +30,129 @@ note: ...which requires building MIR for `cycle1`...
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:14:5
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires computing type of `cycle2::{opaque#0}`...
+  --> $DIR/auto-trait-leak.rs:20:16
+   |
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires borrow-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:20:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/auto-trait-leak.rs:1:1
+   |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+...  |
+LL | |     Rc::new(String::from("foo"))
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
+  --> $DIR/auto-trait-leak.rs:12:16
    |
-LL |     send(cycle2().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
+   |
+note: ...which requires borrow-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing MIR for `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires unsafety-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires computing type of `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:19:16
+  --> $DIR/auto-trait-leak.rs:20:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:5
+  --> $DIR/auto-trait-leak.rs:20:1
    |
-LL |     send(cycle1().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:1:1
@@ -84,6 +166,6 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
index cf2773f4ef5..35994e4a5ba 100644
--- a/src/test/ui/impl-trait/auto-trait.rs
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -19,7 +19,7 @@ impl<T: Send> AnotherTrait for T {}
 // (We treat opaque types as "foreign types" that could grow more impls
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 26cd8fb6a9b..81009413c9a 100644
--- a/src/test/ui/impl-trait/auto-trait.stderr
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
   --> $DIR/auto-trait.rs:21:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs
index 8ec06e534d1..20ddad0547e 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.rs
+++ b/src/test/ui/impl-trait/bound-normalization-fail.rs
@@ -23,8 +23,8 @@ mod impl_trait {
 
     /// `T::Assoc` can't be normalized any further here.
     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
-        //~^ ERROR: type mismatch
         Foo(())
+        //~^ ERROR: type mismatch
     }
 }
 
@@ -39,9 +39,9 @@ mod lifetimes {
 
     /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further.
     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
-        //~^ ERROR: type mismatch
-        //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
+        //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
         Foo(())
+        //~^ ERROR: type mismatch
     }
 }
 
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr
index afa21c1a858..01fb853e1d1 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.stderr
+++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr
@@ -1,16 +1,16 @@
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:25:32
+  --> $DIR/bound-normalization-fail.rs:26:9
    |
-LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+LL |         Foo(())
+   |         ^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
    |
-note: expected this to be `<T as impl_trait::Trait>::Assoc`
+note: expected this to be `()`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note: expected associated type `<T as impl_trait::Trait>::Assoc`
-                    found unit type `()`
+   = note:    expected unit type `()`
+           found associated type `<T as impl_trait::Trait>::Assoc`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
@@ -23,18 +23,18 @@ LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
-  --> $DIR/bound-normalization-fail.rs:41:41
+  --> $DIR/bound-normalization-fail.rs:43:9
    |
-LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
+LL |         Foo(())
+   |         ^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
    |
-note: expected this to be `<T as lifetimes::Trait<'static>>::Assoc`
+note: expected this to be `()`
   --> $DIR/bound-normalization-fail.rs:14:19
    |
 LL |     type Output = T;
    |                   ^
-   = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
-                    found unit type `()`
+   = note:    expected unit type `()`
+           found associated type `<T as lifetimes::Trait<'static>>::Assoc`
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
diff --git a/src/test/ui/impl-trait/does-not-live-long-enough.stderr b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
index f4bd0fde3b6..750687e2322 100644
--- a/src/test/ui/impl-trait/does-not-live-long-enough.stderr
+++ b/src/test/ui/impl-trait/does-not-live-long-enough.stderr
@@ -7,10 +7,10 @@ LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref
    |                                 may outlive borrowed value `prefix`
    |
 note: closure is returned here
-  --> $DIR/does-not-live-long-enough.rs:5:55
+  --> $DIR/does-not-live-long-enough.rs:6:9
    |
-LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword
    |
 LL |         self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref())
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 536a4726c6d..185a3f53f65 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -12,19 +12,13 @@ error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
 LL | fn two(x: bool) -> impl Foo {
-   |                    -------- expected because this return type...
-LL |     if x {
-LL |         return 1_i32;
-   |                ----- ...is found to be `i32` here
-LL |     }
+   |                    -------- the expected opaque type
+...
 LL |     0_u32
    |     ^^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = help: if the trait `Foo` were object safe, you could return a boxed trait object
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
+   = note: expected opaque type `impl Foo`
+                     found type `u32`
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 46053c6e7c1..fd33fa7c674 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -15,9 +15,7 @@ LL | fn hide<T: Foo>(x: T) -> impl Foo {
    |                          -------- the found opaque type
 ...
 LL |     let _: u32 = hide(0_u32);
-   |            ---   ^^^^^^^^^^^ expected `u32`, found opaque type
-   |            |
-   |            expected due to this
+   |                  ^^^^^^^^^^^ expected `u32`, found opaque type
    |
    = note:     expected type `u32`
            found opaque type `impl Foo`
diff --git a/src/test/ui/impl-trait/fallback.rs b/src/test/ui/impl-trait/fallback.rs
new file mode 100644
index 00000000000..1e6eb5bb355
--- /dev/null
+++ b/src/test/ui/impl-trait/fallback.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+fn take_edge_counters(
+    x: &mut Option<Vec<i32>>,
+) -> Option<impl Iterator<Item = i32>> {
+    x.take().map_or(None, |m| Some(m.into_iter()))
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.rs b/src/test/ui/impl-trait/hidden-lifetimes.rs
index 2ee004a37a6..ae07c892768 100644
--- a/src/test/ui/impl-trait/hidden-lifetimes.rs
+++ b/src/test/ui/impl-trait/hidden-lifetimes.rs
@@ -26,8 +26,8 @@ impl<T> Swap for Rc<RefCell<T>> {
 // Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and
 // `&'a mut &'l T` are the same type.
 fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
-    //~^ ERROR hidden type
     x
+    //~^ ERROR hidden type
 }
 
 fn dangle_ref() -> &'static [i32; 3] {
@@ -43,8 +43,8 @@ fn dangle_ref() -> &'static [i32; 3] {
 // This is different to the previous example because the concrete return type
 // only has a single lifetime.
 fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
-    //~^ ERROR hidden type
     x
+    //~^ ERROR hidden type
 }
 
 fn dangle_rc_refcell() -> &'static [i32; 3] {
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr
index c6d11293eec..97652f5462e 100644
--- a/src/test/ui/impl-trait/hidden-lifetimes.stderr
+++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:28:54
+  --> $DIR/hidden-lifetimes.rs:29:5
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
-   |                 --                                   ^^^^^^^^^^^^^^
-   |                 |
-   |                 hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
+   |                 -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -12,12 +12,12 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
    |                                                                     ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:45:70
+  --> $DIR/hidden-lifetimes.rs:46:5
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
-   |                        --                                            ^^^^^^^^^^^^^^
-   |                        |
-   |                        hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+   |                        -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs
new file mode 100644
index 00000000000..1b65685a6c0
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs
@@ -0,0 +1,34 @@
+// This doesn't work, because we don't flow information from opaque types
+// into function arguments via the function's generic parameters
+// FIXME(oli-obk): make `expected_inputs_for_expected_output` support this
+
+fn reify_as() -> Thunk<impl FnOnce(Continuation) -> Continuation> {
+    Thunk::new(|mut cont| { //~ ERROR type annotations needed
+        cont.reify_as();
+        cont
+    })
+}
+
+#[must_use]
+struct Thunk<F>(F);
+
+impl<F> Thunk<F> {
+    fn new(f: F) -> Self
+    where
+        F: ContFn,
+    {
+        Thunk(f)
+    }
+}
+
+trait ContFn {}
+
+impl<F: FnOnce(Continuation) -> Continuation> ContFn for F {}
+
+struct Continuation;
+
+impl Continuation {
+    fn reify_as(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr
new file mode 100644
index 00000000000..e538aaeb4c5
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/hidden-type-is-opaque-2.rs:6:17
+   |
+LL |     Thunk::new(|mut cont| {
+   |                 ^^^^^^^^ consider giving this closure parameter a type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque.rs b/src/test/ui/impl-trait/hidden-type-is-opaque.rs
new file mode 100644
index 00000000000..b302ae36ef4
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+fn reify_as() -> Thunk<impl ContFn> {
+    Thunk::new(|mut cont| {
+        cont.reify_as();
+        cont
+    })
+}
+
+#[must_use]
+struct Thunk<F>(F);
+
+impl<F> Thunk<F> {
+    fn new(f: F) -> Self
+    where
+        F: FnOnce(Continuation) -> Continuation,
+    {
+        Thunk(f)
+    }
+}
+
+trait ContFn {}
+
+impl<F: FnOnce(Continuation) -> Continuation> ContFn for F {}
+
+struct Continuation;
+
+impl Continuation {
+    fn reify_as(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872-1.rs b/src/test/ui/impl-trait/issue-55872-1.rs
index 46188636475..a75b9b43b3e 100644
--- a/src/test/ui/impl-trait/issue-55872-1.rs
+++ b/src/test/ui/impl-trait/issue-55872-1.rs
@@ -10,11 +10,10 @@ impl<S: Default> Bar for S {
     type E = impl Copy;
 
     fn foo<T: Default>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR impl has stricter requirements than trait
-        //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
-        //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
+        //~^ ERROR impl has stricter requirements than trait
         (S::default(), T::default())
+        //~^ ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
+        //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
     }
 }
 
diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr
index 2d1142fd0c5..efc57da7461 100644
--- a/src/test/ui/impl-trait/issue-55872-1.stderr
+++ b/src/test/ui/impl-trait/issue-55872-1.stderr
@@ -8,10 +8,10 @@ LL |     fn foo<T: Default>() -> Self::E {
    |               ^^^^^^^ impl has extra requirement `T: Default`
 
 error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:29
+  --> $DIR/issue-55872-1.rs:14:9
    |
-LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
+LL |         (S::default(), T::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
@@ -20,10 +20,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
    |                 +++++++++++++++++++
 
 error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:29
+  --> $DIR/issue-55872-1.rs:14:9
    |
-LL |     fn foo<T: Default>() -> Self::E {
-   |                             ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
+LL |         (S::default(), T::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
 help: consider further restricting this bound
@@ -31,20 +31,7 @@ help: consider further restricting this bound
 LL |     fn foo<T: Default + std::marker::Copy>() -> Self::E {
    |                       +++++++++++++++++++
 
-error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-1.rs:12:37
-   |
-LL |       fn foo<T: Default>() -> Self::E {
-   |  _____________________________________^
-LL | |
-LL | |
-LL | |
-LL | |
-LL | |         (S::default(), T::default())
-LL | |     }
-   | |_____^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0276, E0277.
 For more information about an error, try `rustc --explain E0276`.
diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs
index 1841d7b3d37..4443d3c4d0d 100644
--- a/src/test/ui/impl-trait/issue-55872-2.rs
+++ b/src/test/ui/impl-trait/issue-55872-2.rs
@@ -3,17 +3,16 @@
 #![feature(type_alias_impl_trait)]
 
 pub trait Bar {
-    type E: Copy;
+    type E: Send;
 
     fn foo<T>() -> Self::E;
 }
 
 impl<S> Bar for S {
-    type E = impl std::marker::Copy;
+    type E = impl std::marker::Send;
     fn foo<T>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-        //~| ERROR the trait bound `impl Future: Copy` is not satisfied
         async {}
+        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr
index 76122e60c4c..11b8485c8bb 100644
--- a/src/test/ui/impl-trait/issue-55872-2.stderr
+++ b/src/test/ui/impl-trait/issue-55872-2.stderr
@@ -1,20 +1,8 @@
-error[E0277]: the trait bound `impl Future: Copy` is not satisfied
-  --> $DIR/issue-55872-2.rs:13:20
-   |
-LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future`
-
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:13:28
+  --> $DIR/issue-55872-2.rs:14:9
    |
-LL |       fn foo<T>() -> Self::E {
-   |  ____________________________^
-LL | |
-LL | |
-LL | |         async {}
-LL | |     }
-   | |_____^
+LL |         async {}
+   |         ^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs
new file mode 100644
index 00000000000..bc2d0b1d757
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-3.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// ignore-compare-mode-chalk
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Bar {
+    type E: Copy;
+
+    fn foo<T>() -> Self::E;
+}
+
+impl<S> Bar for S {
+    type E = impl std::marker::Copy;
+    fn foo<T>() -> Self::E {
+        async {}
+        //~^ ERROR the trait bound `impl Future: Copy` is not satisfied [E0277]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr
new file mode 100644
index 00000000000..69a5c8d6135
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-55872-3.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `impl Future: Copy` is not satisfied
+  --> $DIR/issue-55872-3.rs:15:9
+   |
+LL |         async {}
+   |         ^^^^^^^^ the trait `Copy` is not implemented for `impl Future`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issue-55872.rs b/src/test/ui/impl-trait/issue-55872.rs
index 183728b0f7f..c4e6f643608 100644
--- a/src/test/ui/impl-trait/issue-55872.rs
+++ b/src/test/ui/impl-trait/issue-55872.rs
@@ -10,8 +10,8 @@ impl<S> Bar for S {
     type E = impl Copy;
 
     fn foo<T>() -> Self::E {
-        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         || ()
+        //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
diff --git a/src/test/ui/impl-trait/issue-55872.stderr b/src/test/ui/impl-trait/issue-55872.stderr
index 39d870dc003..cb370fbe1c4 100644
--- a/src/test/ui/impl-trait/issue-55872.stderr
+++ b/src/test/ui/impl-trait/issue-55872.stderr
@@ -1,12 +1,8 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872.rs:12:28
+  --> $DIR/issue-55872.rs:13:9
    |
-LL |       fn foo<T>() -> Self::E {
-   |  ____________________________^
-LL | |
-LL | |         || ()
-LL | |     }
-   | |_____^
+LL |         || ()
+   |         ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs
index dee5a41f6de..cf2c8b7e415 100644
--- a/src/test/ui/impl-trait/issue-72911.rs
+++ b/src/test/ui/impl-trait/issue-72911.rs
@@ -5,7 +5,7 @@ pub struct Lint {}
 impl Lint {}
 
 pub fn gather_all() -> impl Iterator<Item = Lint> {
-    //~^ ERROR: cannot resolve opaque type
+    //~^ ERROR `()` is not an iterator
     lint_files().flat_map(|f| gather_from_file(&f))
 }
 
diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr
index e57fbf104dc..4a990286d96 100644
--- a/src/test/ui/impl-trait/issue-72911.stderr
+++ b/src/test/ui/impl-trait/issue-72911.stderr
@@ -10,25 +10,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo`
 LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
    |                                         ^^^ use of undeclared crate or module `foo`
 
-error[E0720]: cannot resolve opaque type
+error[E0277]: `()` is not an iterator
   --> $DIR/issue-72911.rs:7:24
    |
 LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
-LL |
-LL |     lint_files().flat_map(|f| gather_from_file(&f))
-   |     -----------------------------------------------
-   |     |
-   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-   |     returning here with type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-...
-LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
-   |                                                      -------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
-...
-LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
-   |                    -------------------------------------- returning this opaque type `FlatMap<impl Iterator<Item = [type error]>, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0433, E0720.
-For more information about an error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0277, E0433.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs
index 853c2a82bed..1a86fa00ed1 100644
--- a/src/test/ui/impl-trait/issues/issue-70877.rs
+++ b/src/test/ui/impl-trait/issues/issue-70877.rs
@@ -4,7 +4,7 @@ type FooArg<'a> = &'a dyn ToString;
 type FooRet = impl std::fmt::Debug;
 
 type FooItem = Box<dyn Fn(FooArg) -> FooRet>;
-type Foo = impl Iterator<Item = FooItem>; //~ ERROR: type mismatch
+type Foo = impl Iterator<Item = FooItem>;
 
 #[repr(C)]
 struct Bar(u8);
@@ -13,7 +13,7 @@ impl Iterator for Bar {
     type Item = FooItem;
 
     fn next(&mut self) -> Option<Self::Item> {
-        Some(Box::new(quux))
+        Some(Box::new(quux)) //~ ERROR mismatched types
     }
 }
 
@@ -28,7 +28,7 @@ fn ham() -> Foo {
 fn oof() -> impl std::fmt::Debug {
     let mut bar = ham();
     let func = bar.next().unwrap();
-    return func(&"oof");
+    return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type
 }
 
 fn main() {
diff --git a/src/test/ui/impl-trait/issues/issue-70877.stderr b/src/test/ui/impl-trait/issues/issue-70877.stderr
index fe48e92da5e..7cbd58bdabf 100644
--- a/src/test/ui/impl-trait/issues/issue-70877.stderr
+++ b/src/test/ui/impl-trait/issues/issue-70877.stderr
@@ -1,20 +1,34 @@
-error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:7:12
+error[E0308]: mismatched types
+  --> $DIR/issue-70877.rs:16:9
    |
 LL | type FooRet = impl std::fmt::Debug;
-   |               -------------------- the found opaque type
+   |               -------------------- the expected opaque type
 ...
-LL | type Foo = impl Iterator<Item = FooItem>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
+LL |     fn next(&mut self) -> Option<Self::Item> {
+   |                           ------------------ expected `Option<Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> FooRet + 'static)>>` because of return type
+LL |         Some(Box::new(quux))
+   |         ^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found fn item
    |
-note: expected this to be `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-  --> $DIR/issue-70877.rs:13:17
+   = note: expected enum `Option<Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> FooRet + 'static)>>`
+              found enum `Option<Box<for<'r> fn(&'r (dyn ToString + 'r)) -> FooRet {quux}>>`
+
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/issue-70877.rs:31:12
+   |
+LL |     return func(&"oof");
+   |            ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/issue-70877.rs:28:13
    |
-LL |     type Item = FooItem;
-   |                 ^^^^^^^
-   = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
-              found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
+LL | fn oof() -> impl std::fmt::Debug {
+   |             ^^^^^^^^^^^^^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/issue-70877.rs:4:15
+   |
+LL | type FooRet = impl std::fmt::Debug;
+   |               ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
index bdbd20f9d2b..5498793bc28 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.rs
+++ b/src/test/ui/impl-trait/issues/issue-78722.rs
@@ -7,10 +7,11 @@ type F = impl core::future::Future<Output = u8>;
 struct Bug {
     V1: [(); {
         fn concrete_use() -> F {
-            async {}
+            async {} //~ ERROR type mismatch
         }
         let f: F = async { 1 };
-        //~^ ERROR mismatched types [E0308]
+        //~^ ERROR `async` blocks are not allowed in constants
+        //~| ERROR destructors cannot be evaluated at compile-time
         1
     }],
 }
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
index 86bde9a0cdd..624d85570c7 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.stderr
+++ b/src/test/ui/impl-trait/issues/issue-78722.stderr
@@ -1,23 +1,28 @@
-error[E0308]: mismatched types
+error[E0658]: `async` blocks are not allowed in constants
   --> $DIR/issue-78722.rs:12:20
    |
-LL | type F = impl core::future::Future<Output = u8>;
-   |          -------------------------------------- the expected opaque type
-...
 LL |         let f: F = async { 1 };
-   |                -   ^^^^^^^^^^^ expected opaque type, found a different opaque type
-   |                |
-   |                expected due to this
+   |                    ^^^^^^^^^^^
    |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
+   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
+   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/issue-78722.rs:12:13
    |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
+LL |         let f: F = async { 1 };
+   |             ^ constants cannot evaluate destructors
+...
+LL |     }],
+   |     - value is dropped here
+
+error[E0271]: type mismatch resolving `<impl Future as Future>::Output == u8`
+  --> $DIR/issue-78722.rs:10:13
    |
-   = note: expected opaque type `impl Future<Output = u8>`
-              found opaque type `impl Future`
-   = note: distinct uses of `impl Trait` result in different opaque types
+LL |             async {}
+   |             ^^^^^^^^ expected `()`, found `u8`
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0271, E0493, E0658.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs
index e3386d29def..0786e66ca8b 100644
--- a/src/test/ui/impl-trait/issues/issue-86201.rs
+++ b/src/test/ui/impl-trait/issues/issue-86201.rs
@@ -1,10 +1,10 @@
 #![feature(unboxed_closures)]
 #![feature(type_alias_impl_trait)]
 
+// check-pass
+
 type FunType = impl Fn<()>;
-//~^ ERROR could not find defining uses
 static STATIC_FN: FunType = some_fn;
-//~^ ERROR mismatched types
 
 fn some_fn() {}
 
diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr
deleted file mode 100644
index b1460096ded..00000000000
--- a/src/test/ui/impl-trait/issues/issue-86201.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-86201.rs:6:29
-   |
-LL | type FunType = impl Fn<()>;
-   |                ----------- the expected opaque type
-LL |
-LL | static STATIC_FN: FunType = some_fn;
-   |                             ^^^^^^^ expected opaque type, found fn item
-   |
-   = note: expected opaque type `impl Fn<()>`
-                  found fn item `fn() {some_fn}`
-
-error: could not find defining uses
-  --> $DIR/issue-86201.rs:4:16
-   |
-LL | type FunType = impl Fn<()>;
-   |                ^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr
new file mode 100644
index 00000000000..9cf8ff76c87
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr
@@ -0,0 +1,51 @@
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                  -- lifetime `'b` defined here
+LL |     x
+   |     ^ returning this value requires that `'b` must outlive `'static`
+   |
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'b`, add `'b` as a bound
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b {
+   |                                                                                  ++++
+
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs
new file mode 100644
index 00000000000..f89ab7fbd36
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs
@@ -0,0 +1,23 @@
+// this used to cause stack overflows
+
+trait Hrtb<'a> {
+    type Assoc;
+}
+
+impl<'a> Hrtb<'a> for () {
+    type Assoc = ();
+}
+
+impl<'a> Hrtb<'a> for &'a () {
+    type Assoc = ();
+}
+
+fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    &() //~ ERROR implementation of `Hrtb` is not general enough
+}
+fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+    x //~ ERROR implementation of `Hrtb` is not general enough
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
new file mode 100644
index 00000000000..95c4a528036
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
@@ -0,0 +1,20 @@
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:17:5
+   |
+LL |     &()
+   |     ^^^ implementation of `Hrtb` is not general enough
+   |
+   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:20:5
+   |
+LL |     x
+   |     ^ implementation of `Hrtb` is not general enough
+   |
+   = note: `&()` must implement `Hrtb<'0>`, for any lifetime `'0`...
+   = note: ...but `Hrtb<'_>` is actually implemented for the type `&()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs
new file mode 100644
index 00000000000..2ea35270a7e
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// this used to cause stack overflows
+
+trait Hrtb<'a> {
+    type Assoc;
+}
+
+impl<'a> Hrtb<'a> for () {
+    type Assoc = ();
+}
+
+impl<'a> Hrtb<'a> for &'a () {
+    type Assoc = ();
+}
+
+fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/lifetimes2.rs b/src/test/ui/impl-trait/lifetimes2.rs
new file mode 100644
index 00000000000..834f2dc6cb5
--- /dev/null
+++ b/src/test/ui/impl-trait/lifetimes2.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+pub fn keys<'a>(x: &'a Result<u32, u32>) -> impl std::fmt::Debug + 'a {
+    match x {
+        Ok(map) => Ok(map),
+        Err(map) => Err(map),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
index 72e9d96da36..f5aaf118521 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
@@ -8,7 +8,6 @@ impl<T: Copy> Copy for CopyIfEq<T, T> {}
 type E<'a, 'b> = impl Sized;
 
 fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
-    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
     let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
 
     // This assignment requires that `x` and `y` have the same type due to the
@@ -21,6 +20,7 @@ fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
         let _: &'b i32 = *u.0;
     }
     u.0
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
index 40bec0da270..b837b641103 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/error-handling-2.rs:10:60
+  --> $DIR/error-handling-2.rs:22:5
    |
 LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
-   |        --                                                  ^^^^^^^^^
-   |        |
-   |        hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
+   |        -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
+...
+LL |     u.0
+   |     ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
index 3a97624647e..47e05bce0f8 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
@@ -14,7 +14,6 @@ struct Ordinary<'a>(&'a u8);
 // by both `'a` and `'b`.
 
 fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
-//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 where
     'a: 'e,
     'b: 'd,
@@ -27,6 +26,7 @@ where
     // 'a in ['d, 'e]
     // ```
     if condition() { a } else { b }
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn condition() -> bool {
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index 32829a0a1b2..15476c706a7 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ordinary-bounds-unrelated.rs:16:74
+  --> $DIR/ordinary-bounds-unrelated.rs:28:33
    |
 LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
-   |                     --                                                   ^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+...
+LL |     if condition() { a } else { b }
+   |                                 ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
index d4c60a4e892..321cb8c92a1 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
@@ -16,7 +16,6 @@ struct Ordinary<'a>(&'a u8);
 // consider the loans for both `'a` and `'b` alive.
 
 fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 {
     // We return a value:
     //
@@ -30,6 +29,7 @@ fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
     //
     // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
     if condition() { a } else { b }
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
 }
 
 fn condition() -> bool {
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index 83ad23b253b..7315aa8e9d4 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ordinary-bounds-unsuited.rs:18:62
+  --> $DIR/ordinary-bounds-unsuited.rs:31:33
    |
 LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-   |                     --                                       ^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+...
+LL |     if condition() { a } else { b }
+   |                                 ^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 2f6bd8ff377..eb38f84d4af 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ^^^^^^^^^
+   |              ----                 ^
    |              |
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
@@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             --                 ^^^^^^^^^
+   |             --                             ^
    |             |
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
@@ -67,12 +67,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:33:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:34:5
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-   |                              --                             ^^^^^^^^^^^^^^^^
-   |                              |
-   |                              hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
+   |                              -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here
+LL |     move |_| println!("{}", y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -80,10 +80,10 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                                              ++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:38:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:39:5
    |
-LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                                   ^^^^^^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
index 69d2843ff3f..02ea0255912 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -31,13 +31,13 @@ fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERRO
 // Tests that a closure type containing 'b cannot be returned from a type where
 // only 'a was expected.
 fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-    //~^ ERROR: captures lifetime that does not appear in bounds
     move |_| println!("{}", y)
+    //~^ ERROR: captures lifetime that does not appear in bounds
 }
 
 fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-    //~^ ERROR the parameter type `T` may not live long enough
     x
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 07ac0a8db35..77ba0bf9087 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ^^^^^^^^^
+   |              ----                 ^
    |              |
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
@@ -12,10 +12,10 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             --                 ^^^^^^^^^
+   |             --                             ^
    |             |
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
@@ -28,15 +28,10 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
   --> $DIR/must_outlive_least_region_or_bound.rs:9:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
-   |               ----                           ^ ...is used here...
+   |               ----                           ^ ...is used and required to live as long as `'static` here
    |               |
    |               this data with an anonymous lifetime `'_`...
    |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:24
-   |
-LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
-   |                        ^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
@@ -50,15 +45,10 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:11:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-   |                     -------                           ^ ...is used here...
+   |                     -------                           ^ ...is used and required to live as long as `'static` here
    |                     |
    |                     this data with lifetime `'a`...
    |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:11:33
-   |
-LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-   |                                 ^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
@@ -69,10 +59,10 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
    |                     ~~~~~~~~~~~~
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/must_outlive_least_region_or_bound.rs:13:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:13:41
    |
 LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
-   |               ----     ^^^^^^^^^^^^^^ lifetime `'a` required
+   |               ----                      ^ lifetime `'a` required
    |               |
    |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
 
@@ -95,13 +85,8 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:29:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                      ------- this data with lifetime `'a`...        ^ ...is used here...
-   |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:29:34
+   |                      ------- this data with lifetime `'a`...        ^ ...is used and required to live as long as `'static` here
    |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
@@ -112,12 +97,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x
    |                      ~~~~~~~~~~~~
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:33:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:34:5
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-   |                              --                             ^^^^^^^^^^^^^^^^
-   |                              |
-   |                              hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:35:5: 35:31]` captures the lifetime `'b` as defined here
+   |                              -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:34:5: 34:31]` captures the lifetime `'b` as defined here
+LL |     move |_| println!("{}", y)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
@@ -125,12 +110,12 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                                              ++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:38:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:39:5
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                 --                ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-   |                                 |
-   |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
+   |                                 -- help: consider adding an explicit lifetime bound...: `T: 'static +`
+LL |     x
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/must_outlive_least_region_or_bound.rs:16:50
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
index d173fe83fb7..70e24a3a9d0 100644
--- a/src/test/ui/impl-trait/negative-reasoning.rs
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -17,7 +17,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index e39a8e53f79..6b8cc9e7374 100644
--- a/src/test/ui/impl-trait/negative-reasoning.stderr
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -1,13 +1,13 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
   --> $DIR/negative-reasoning.rs:19:1
    |
 LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
    |
-   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `impl OpaqueTrait` in future versions
+   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
index 06a2191a017..ec2d49d9367 100644
--- a/src/test/ui/impl-trait/nested_impl_trait.rs
+++ b/src/test/ui/impl-trait/nested_impl_trait.rs
@@ -4,6 +4,7 @@ fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
 
 fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
 //~^ ERROR nested `impl Trait` is not allowed
+//~| ERROR `impl Into<u32>` doesn't implement `Debug`
 
 fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
 //~^ ERROR nested `impl Trait` is not allowed
@@ -16,6 +17,7 @@ struct X;
 impl X {
     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
     //~^ ERROR nested `impl Trait` is not allowed
+    //~| ERROR `impl Into<u32>` doesn't implement `Debug`
 }
 
 fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
index 4444e6a454f..248d1254ef7 100644
--- a/src/test/ui/impl-trait/nested_impl_trait.stderr
+++ b/src/test/ui/impl-trait/nested_impl_trait.stderr
@@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:8:42
+  --> $DIR/nested_impl_trait.rs:9:42
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ----------^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:12:37
+  --> $DIR/nested_impl_trait.rs:13:37
    |
 LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           ----------^^^^^^^^^^-
@@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:17:44
+  --> $DIR/nested_impl_trait.rs:18:44
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  ----------^^^^^^^^^^-
@@ -35,18 +35,40 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  outer `impl Trait`
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
-  --> $DIR/nested_impl_trait.rs:8:32
+  --> $DIR/nested_impl_trait.rs:9:32
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/nested_impl_trait.rs:25:42
+  --> $DIR/nested_impl_trait.rs:27:42
    |
 LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
    |                                          ^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error[E0277]: `impl Into<u32>` doesn't implement `Debug`
+  --> $DIR/nested_impl_trait.rs:5:70
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                                                      ^ `impl Into<u32>` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider further restricting this bound
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                                          +++++++++++++++++
+
+error[E0277]: `impl Into<u32>` doesn't implement `Debug`
+  --> $DIR/nested_impl_trait.rs:18:58
+   |
+LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                                          ^ `impl Into<u32>` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider further restricting this bound
+   |
+LL |     fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                              +++++++++++++++++
+
+error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0562, E0666.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0277, E0562, E0666.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
index 357166d1123..b2f7166f0ae 100644
--- a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
@@ -2,46 +2,25 @@ error[E0308]: mismatched types
   --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
    |
 LL | fn can() -> impl NotObjectSafe {
-   |             ------------------ expected because this return type...
-LL |     if true {
-LL |         return A;
-   |                - ...is found to be `A` here
-LL |     }
+   |             ------------------ the expected opaque type
+...
 LL |     B
    |     ^ expected struct `A`, found struct `B`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
+   = note: expected opaque type `impl NotObjectSafe`
+                   found struct `B`
 
 error[E0308]: mismatched types
   --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
    |
 LL | fn cat() -> impl ObjectSafe {
-   |             --------------- expected because this return type...
-LL |     if true {
-LL |         return A;
-   |                - ...is found to be `A` here
-LL |     }
+   |             --------------- the expected opaque type
+...
 LL |     B
    |     ^ expected struct `A`, found struct `B`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn cat() -> Box<dyn ObjectSafe> {
-   |             ~~~~~~~           +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(A);
-LL |     }
-LL ~     Box::new(B)
-   |
+   = note: expected opaque type `impl ObjectSafe`
+                   found struct `B`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
index fa7664a83ee..9f9a6c784e6 100644
--- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
+++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
@@ -14,10 +14,10 @@ fn bar() -> impl std::fmt::Display {
 }
 
 fn baz() -> impl std::fmt::Display {
-    if false {
+    if false { //~ ERROR mismatched types
         return 0i32;
     } else {
-        1u32 //~ ERROR mismatched types
+        1u32
     }
 }
 
@@ -30,9 +30,9 @@ fn qux() -> impl std::fmt::Display {
 }
 
 fn bat() -> impl std::fmt::Display {
-    match 13 {
+    match 13 { //~ ERROR mismatched types
         0 => return 0i32,
-        _ => 1u32, //~ ERROR mismatched types
+        _ => 1u32,
     }
 }
 
@@ -45,12 +45,12 @@ fn can() -> impl std::fmt::Display {
 }
 
 fn cat() -> impl std::fmt::Display {
-    match 13 {
+    match 13 { //~ ERROR mismatched types
         0 => {
             return 0i32;
         }
         _ => {
-            1u32 //~ ERROR mismatched types
+            1u32
         }
     }
 }
diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
index 970abad5c72..db0d446e559 100644
--- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -2,82 +2,40 @@ error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
    |
 LL | fn foo() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     }
+   |             ---------------------- the expected opaque type
+...
 LL |     1u32
    |     ^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn foo() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(0i32);
-LL |     }
-LL ~     Box::new(1u32)
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16
    |
 LL | fn bar() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     } else {
+   |             ---------------------- the expected opaque type
+...
 LL |         return 1u32;
    |                ^^^^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn bar() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         return Box::new(0i32);
-LL |     } else {
-LL ~         return Box::new(1u32);
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9
-   |
-LL | fn baz() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     if false {
-LL |         return 0i32;
-   |                ---- ...is found to be `i32` here
-LL |     } else {
-LL |         1u32
-   |         ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn baz() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:17:5
    |
-LL ~         return Box::new(0i32);
-LL |     } else {
-LL ~         Box::new(1u32)
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     if false {
+LL | |         return 0i32;
+LL | |     } else {
+LL | |         1u32
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9
@@ -103,87 +61,50 @@ LL ~         Box::new(1u32)
    |
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14
-   |
-LL | fn bat() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-LL |     match 13 {
-LL |         0 => return 0i32,
-   |                     ---- ...is found to be `i32` here
-LL |         _ => 1u32,
-   |              ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn bat() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:33:5
    |
-LL ~         0 => return Box::new(0i32),
-LL ~         _ => Box::new(1u32),
+LL |   fn bat() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     match 13 {
+LL | |         0 => return 0i32,
+LL | |         _ => 1u32,
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5
    |
 LL |   fn can() -> impl std::fmt::Display {
-   |               ---------------------- expected because this return type...
+   |               ---------------------- the expected opaque type
 LL | /     match 13 {
 LL | |         0 => return 0i32,
-   | |                     ---- ...is found to be `i32` here
 LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____^ expected `i32`, found `u32`
    |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn can() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~     Box::new(match 13 {
-LL ~         0 => return Box::new(0i32),
-LL |         1 => 1u32,
-LL |         _ => 2u32,
-LL ~     })
-   |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: mismatched types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
+  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:48:5
    |
-LL | fn cat() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-...
-LL |             return 0i32;
-   |                    ---- ...is found to be `i32` here
-...
-LL |             1u32
-   |             ^^^^ expected `i32`, found `u32`
-   |
-   = note: to return `impl Trait`, all returned values must be of the same type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = help: you could instead create a new `enum` with a variant for each returned type
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn cat() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~             return Box::new(0i32);
-LL |         }
-LL |         _ => {
-LL ~             Box::new(1u32)
+LL |   fn cat() -> impl std::fmt::Display {
+   |               ---------------------- the expected opaque type
+LL | /     match 13 {
+LL | |         0 => {
+LL | |             return 0i32;
+LL | |         }
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ expected `i32`, found `u32`
    |
+   = note: expected opaque type `impl std::fmt::Display`
+                     found type `u32`
 
 error[E0308]: `match` arms have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14
@@ -196,16 +117,6 @@ LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____- `match` arms have incompatible types
-   |
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn dog() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         0 => Box::new(0i32),
-LL ~         1 => Box::new(1u32),
-   |
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
@@ -218,17 +129,6 @@ LL | |         1u32
    | |         ^^^^ expected `i32`, found `u32`
 LL | |     }
    | |_____- `if` and `else` have incompatible types
-   |
-help: you could change the return type to be a boxed trait object
-   |
-LL | fn apt() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         Box::new(0i32)
-LL |     } else {
-LL ~         Box::new(1u32)
-   |
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
index b4fd6b3e743..2e7cb21592c 100644
--- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs
@@ -11,8 +11,8 @@ pub trait Test {}
 impl<T> Test for T where T: Super<Assoc = ()> {}
 
 fn test() -> impl Test {
-    //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
     ()
+    //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()`
 }
 
 fn main() {
diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
index 65daabe419d..5ef1e9abef6 100644
--- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
@@ -1,10 +1,10 @@
 error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
-  --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14
+  --> $DIR/projection-mismatch-in-impl-where-clause.rs:14:5
    |
-LL | fn test() -> impl Test {
-   |              ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()`
+LL |     ()
+   |     ^^ type mismatch resolving `<() as Super>::Assoc == ()`
    |
-note: expected this to be `()`
+note: expected this to be `u8`
   --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18
    |
 LL |     type Assoc = u8;
diff --git a/src/test/ui/impl-trait/question_mark.rs b/src/test/ui/impl-trait/question_mark.rs
new file mode 100644
index 00000000000..211f7972dbc
--- /dev/null
+++ b/src/test/ui/impl-trait/question_mark.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+fn foo() -> impl MyTrait {
+    panic!();
+    MyStruct
+}
+
+struct MyStruct;
+trait MyTrait {}
+
+impl MyTrait for MyStruct {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs
index 3cc53744097..540a280f0a3 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs
@@ -1,9 +1,8 @@
-// Test that an `impl Trait` type that expands to itself is an error.
+// check-pass
 
 #![allow(unconditional_recursion)]
 
 fn test() -> impl Sized {
-    //~^ ERROR E0720
     test()
 }
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
deleted file mode 100644
index 5a3027ec751..00000000000
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-impl-trait-type-direct.rs:5:14
-   |
-LL | fn test() -> impl Sized {
-   |              ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     test()
-   |     ------ returning here with type `impl Sized`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index e3c621f0c57..ffc0cd9d10c 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -5,7 +5,7 @@
 #![allow(unconditional_recursion)]
 
 fn option(i: i32) -> impl Sized {
-    //~^ ERROR
+    //~^ ERROR cannot resolve opaque type
     if i < 0 { None } else { Some((option(i - 1), i)) }
 }
 
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
new file mode 100644
index 00000000000..a60e34c17b6
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -0,0 +1,29 @@
+#![feature(type_alias_impl_trait)]
+
+mod a {
+    type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR unconstrained opaque type
+
+    struct Bar;
+
+    impl PartialEq<(Bar, i32)> for Bar {
+        fn eq(&self, _other: &(Foo, i32)) -> bool {
+            true
+        }
+    }
+}
+
+mod b {
+    type Foo = impl PartialEq<(Foo, i32)>;
+    //~^ ERROR unconstrained opaque type
+
+    struct Bar;
+
+    impl PartialEq<(Foo, i32)> for Bar {
+        fn eq(&self, _other: &(Bar, i32)) -> bool {
+            true
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
new file mode 100644
index 00000000000..eae7d38d116
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -0,0 +1,18 @@
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:17:16
+   |
+LL |     type Foo = impl PartialEq<(Foo, i32)>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
new file mode 100644
index 00000000000..bdabc13c36a
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -0,0 +1,37 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+mod direct {
+    type Foo = impl PartialEq<(Foo, i32)>;
+
+    struct Bar;
+
+    impl PartialEq<(Foo, i32)> for Bar {
+        fn eq(&self, _other: &(Foo, i32)) -> bool {
+            true
+        }
+    }
+
+    fn foo() -> Foo {
+        Bar
+    }
+}
+
+mod indirect {
+    type Foo = impl PartialEq<(Foo, i32)>;
+
+    struct Bar;
+
+    impl PartialEq<(Bar, i32)> for Bar {
+        fn eq(&self, _other: &(Bar, i32)) -> bool {
+            true
+        }
+    }
+
+    fn foo() -> Foo {
+        Bar
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs
index e834f96dbbe..a04cb1702b6 100644
--- a/src/test/ui/impl-trait/region-escape-via-bound.rs
+++ b/src/test/ui/impl-trait/region-escape-via-bound.rs
@@ -12,10 +12,10 @@ trait Trait<'a> { }
 impl<'a, 'b> Trait<'b> for Cell<&'a u32> { }
 
 fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
-    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
 where 'x: 'y
 {
     x
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
 }
 
 fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
index ecec34e0115..bc02f7694d7 100644
--- a/src/test/ui/impl-trait/region-escape-via-bound.stderr
+++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/region-escape-via-bound.rs:14:37
+  --> $DIR/region-escape-via-bound.rs:17:5
    |
 LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
-   |        --                           ^^^^^^^^^^^^^^
-   |        |
-   |        hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
+   |        -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
+...
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
index d792c6eafb3..f940c1949d0 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs
@@ -4,14 +4,14 @@ struct A {
 
 impl A {
     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
         //~| ERROR: captures lifetime that does not appear in bounds
-        self.x.iter().map(|a| a.0)
     }
     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+        self.x.iter().map(|a| a.0)
         //~^ ERROR: captures lifetime that does not appear in bounds
         //~| ERROR: captures lifetime that does not appear in bounds
-        self.x.iter().map(|a| a.0)
     }
 }
 
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index 7424da76182..bc8e39f9c50 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:6:35
+  --> $DIR/static-return-lifetime-infered.rs:7:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ^^^^^^^^^^^^^^^^^^^^^^^
-   |                         |
-   |                         hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
+   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
    |
@@ -12,12 +12,12 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:6:35
+  --> $DIR/static-return-lifetime-infered.rs:7:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ^^^^^^^^^^^^^^^^^^^^^^^
-   |                         |
-   |                         hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:9:27: 9:34]>` captures the anonymous lifetime defined here
+   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:34]>` captures the anonymous lifetime defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
    |
@@ -25,12 +25,12 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:11:37
+  --> $DIR/static-return-lifetime-infered.rs:12:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    --               ^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
+   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
    |
@@ -38,12 +38,12 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ++++
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/static-return-lifetime-infered.rs:11:37
+  --> $DIR/static-return-lifetime-infered.rs:12:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    --               ^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:14:27: 14:34]>` captures the lifetime `'a` as defined here
+   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:34]>` captures the lifetime `'a` as defined here
+LL |         self.x.iter().map(|a| a.0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
    |
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.rs b/src/test/ui/impl-trait/two_tait_defining_each_other.rs
new file mode 100644
index 00000000000..6eb2a11b22c
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    if false {
+        return Bar; // B's hidden type is Bar
+    }
+    x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
+    //~^ ERROR opaque type's hidden type cannot be another opaque type
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr
new file mode 100644
index 00000000000..1a42ac525a6
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other.stderr
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other.rs:12:5
+   |
+LL |     x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
+   |     ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.rs b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs
new file mode 100644
index 00000000000..3b16d0f5e04
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    x // B's hidden type is A (opaquely)
+    //~^ ERROR opaque type's hidden type cannot be another opaque type
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr
new file mode 100644
index 00000000000..ef2089a6c5b
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other2.rs:9:5
+   |
+LL |     x // B's hidden type is A (opaquely)
+   |     ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other2.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other2.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.rs b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs
new file mode 100644
index 00000000000..37f8ae1b84b
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+type A = impl Foo;
+type B = impl Foo;
+
+trait Foo {}
+
+fn muh(x: A) -> B {
+    if false {
+        return x;  // B's hidden type is A (opaquely)
+        //~^ ERROR opaque type's hidden type cannot be another opaque type
+    }
+    Bar // A's hidden type is `Bar`, because all the return types are compared with each other
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr
new file mode 100644
index 00000000000..b06dc16d5e7
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other3.stderr
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/two_tait_defining_each_other3.rs:10:16
+   |
+LL |         return x;  // B's hidden type is A (opaquely)
+   |                ^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/two_tait_defining_each_other3.rs:4:10
+   |
+LL | type B = impl Foo;
+   |          ^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/two_tait_defining_each_other3.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
index 039cb62f866..e0b77544d43 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr
@@ -1,8 +1,8 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/type_parameters_captured.rs:7:20
+  --> $DIR/type_parameters_captured.rs:8:5
    |
-LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |                    ^^^^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
diff --git a/src/test/ui/impl-trait/type_parameters_captured.rs b/src/test/ui/impl-trait/type_parameters_captured.rs
index 6c9c9d4a42a..81ee7d3f8a5 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.rs
+++ b/src/test/ui/impl-trait/type_parameters_captured.rs
@@ -5,8 +5,8 @@ impl<T> Any for T {}
 
 // Check that type parameters are captured and not considered 'static
 fn foo<T>(x: T) -> impl Any + 'static {
-    //~^ ERROR the parameter type `T` may not live long enough
     x
+    //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr
index 40e50b9922f..c0de4f4b4a0 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -1,10 +1,10 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/type_parameters_captured.rs:7:20
+  --> $DIR/type_parameters_captured.rs:8:5
    |
 LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |        -           ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-   |        |
-   |        help: consider adding an explicit lifetime bound...: `T: 'static`
+   |        - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL |     x
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs
index 462508f306e..d5a87b5d468 100644
--- a/src/test/ui/impl-trait/where-allowed-2.rs
+++ b/src/test/ui/impl-trait/where-allowed-2.rs
@@ -1,8 +1,7 @@
-//! Ideally, these tests would go in `where-allowed.rs`, but we bail out
-//! too early to display them.
 use std::fmt::Debug;
 
-// Disallowed
-fn in_adt_in_return() -> Vec<impl Debug> { panic!() } //~ ERROR cannot resolve opaque type
+// check-pass
+
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
deleted file mode 100644
index b8e06725cbc..00000000000
--- a/src/test/ui/impl-trait/where-allowed-2.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0720]: cannot resolve opaque type
-  --> $DIR/where-allowed-2.rs:6:30
-   |
-LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-   |                              ^^^^^^^^^^    -------- this returned value is of `!` type
-   |                              |
-   |                              cannot resolve opaque type
-   |
-   = help: this error will resolve once the item's body returns a concrete type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.