about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-30 05:04:45 +0000
committerbors <bors@rust-lang.org>2022-03-30 05:04:45 +0000
commitf132bcf3bdf6d3ff9be7d02e8d0088b99007cd5e (patch)
treea05f563d1b317376019f4856c5d80c45708de370 /src/test
parent1446d17b8f4bd3ff8dbfb129a7674165e06f9f4c (diff)
parent638f84d782e9d8ad4fe5f35fea75088c11986e51 (diff)
downloadrust-f132bcf3bdf6d3ff9be7d02e8d0088b99007cd5e.tar.gz
rust-f132bcf3bdf6d3ff9be7d02e8d0088b99007cd5e.zip
Auto merge of #94081 - oli-obk:lazy_tait_take_two, r=nikomatsakis
Lazy type-alias-impl-trait take two

### user visible change 1: RPIT inference from recursive call sites

Lazy TAIT has an insta-stable change. The following snippet now compiles, because opaque types can now have their hidden type set from wherever the opaque type is mentioned.

```rust
fn bar(b: bool) -> impl std::fmt::Debug {
    if b {
        return 42
    }
    let x: u32 = bar(false); // this errors on stable
    99
}
```

The return type of `bar` stays opaque, you can't do `bar(false) + 42`, you need to actually mention the hidden type.

### user visible change 2: divergence between RPIT and TAIT in return statements

Note that `return` statements and the trailing return expression are special with RPIT (but not TAIT). So

```rust
#![feature(type_alias_impl_trait)]
type Foo = impl std::fmt::Debug;

fn foo(b: bool) -> Foo {
    if b {
        return vec![42];
    }
    std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator
}

fn bar(b: bool) -> impl std::fmt::Debug {
    if b {
        return vec![42]
    }
    std::iter::empty().collect() // Works, magic (accidentally stabilized, not intended)
}
```

But when we are working with the return value of a recursive call, the behavior of RPIT and TAIT is the same:

```rust
type Foo = impl std::fmt::Debug;

fn foo(b: bool) -> Foo {
    if b {
        return vec![];
    }
    let mut x = foo(false);
    x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator
    vec![]
}

fn bar(b: bool) -> impl std::fmt::Debug {
    if b {
        return vec![];
    }
    let mut x = bar(false);
    x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator
    vec![]
}
```

### user visible change 3: TAIT does not merge types across branches

In contrast to RPIT, TAIT does not merge types across branches, so the following does not compile.

```rust
type Foo = impl std::fmt::Debug;

fn foo(b: bool) -> Foo {
    if b {
        vec![42_i32]
    } else {
        std::iter::empty().collect()
        //~^ ERROR `Foo` cannot be built from an iterator over elements of type `_`
    }
}
```

It is easy to support, but we should make an explicit decision to include the additional complexity in the implementation (it's not much, see a721052457cf513487fb4266e3ade65c29b272d2 which needs to be reverted to enable this).

### PR formalities

previous attempt: #92007

This PR also includes #92306 and #93783, as they were reverted along with #92007 in #93893

fixes #93411
fixes #88236
fixes #89312
fixes #87340
fixes #86800
fixes #86719
fixes #84073
fixes #83919
fixes #82139
fixes #77987
fixes #74282
fixes #67830
fixes #62742
fixes #54895
Diffstat (limited to 'src/test')
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs2
-rw-r--r--src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs2
-rw-r--r--src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr8
-rw-r--r--src/test/ui/associated-types/impl-trait-return-missing-constraint.rs3
-rw-r--r--src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr35
-rw-r--r--src/test/ui/async-await/async-borrowck-escaping-block-error.stderr6
-rw-r--r--src/test/ui/async-await/issue-70818.rs2
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr14
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr29
-rw-r--r--src/test/ui/async-await/no-const-async.rs1
-rw-r--r--src/test/ui/async-await/no-const-async.stderr33
-rw-r--r--src/test/ui/async-await/recursive-async-impl-trait-type.rs3
-rw-r--r--src/test/ui/async-await/suggest-missing-await.rs2
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr9
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr6
-rw-r--r--src/test/ui/conservative_impl_trait.rs1
-rw-r--r--src/test/ui/conservative_impl_trait.stderr14
-rw-r--r--src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs3
-rw-r--r--src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr50
-rw-r--r--src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs2
-rw-r--r--src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr25
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs11
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr73
-rw-r--r--src/test/ui/generator/issue-88653.rs10
-rw-r--r--src/test/ui/generator/issue-88653.stderr18
-rw-r--r--src/test/ui/generator/type-mismatch-signature-deduction.rs4
-rw-r--r--src/test/ui/generator/type-mismatch-signature-deduction.stderr30
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-86218.stderr12
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-89008.stderr26
-rw-r--r--src/test/ui/generic-associated-types/issue-87258_a.rs3
-rw-r--r--src/test/ui/generic-associated-types/issue-87258_a.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-87258_b.rs3
-rw-r--r--src/test/ui/generic-associated-types/issue-87258_b.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-88595.rs1
-rw-r--r--src/test/ui/generic-associated-types/issue-88595.stderr12
-rw-r--r--src/test/ui/impl-trait/async_scope_creep.rs28
-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/autoderef.rs19
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.rs6
-rw-r--r--src/test/ui/impl-trait/bound-normalization-fail.stderr65
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.rs45
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.stderr26
-rw-r--r--src/test/ui/impl-trait/divergence.rs13
-rw-r--r--src/test/ui/impl-trait/does-not-live-long-enough.stderr6
-rw-r--r--src/test/ui/impl-trait/equality.stderr13
-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.rs45
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr19
-rw-r--r--src/test/ui/impl-trait/hidden-type-is-opaque.rs42
-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/issue-86465.rs2
-rw-r--r--src/test/ui/impl-trait/issue-86465.stderr15
-rw-r--r--src/test/ui/impl-trait/issues/issue-54895.rs23
-rw-r--r--src/test/ui/impl-trait/issues/issue-62742.rs32
-rw-r--r--src/test/ui/impl-trait/issues/issue-62742.stderr54
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.nll.stderr20
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.rs26
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.stderr15
-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-74282.rs11
-rw-r--r--src/test/ui/impl-trait/issues/issue-74282.stderr33
-rw-r--r--src/test/ui/impl-trait/issues/issue-77987.rs21
-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-82139.rs19
-rw-r--r--src/test/ui/impl-trait/issues/issue-82139.stderr9
-rw-r--r--src/test/ui/impl-trait/issues/issue-83919.rs31
-rw-r--r--src/test/ui/impl-trait/issues/issue-83919.stderr17
-rw-r--r--src/test/ui/impl-trait/issues/issue-84073.rs33
-rw-r--r--src/test/ui/impl-trait/issues/issue-84073.stderr9
-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-86719.rs12
-rw-r--r--src/test/ui/impl-trait/issues/issue-86719.stderr24
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.rs48
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.stderr10
-rw-r--r--src/test/ui/impl-trait/issues/issue-87340.rs14
-rw-r--r--src/test/ui/impl-trait/issues/issue-87340.stderr9
-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.stderr23
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.rs19
-rw-r--r--src/test/ui/impl-trait/issues/issue-89312.rs24
-rw-r--r--src/test/ui/impl-trait/issues/issue-93788.rs27
-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.rs3
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr31
-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-return-type2-tait.rs32
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.stderr32
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.rs32
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.stderr15
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.rs31
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.stderr15
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.rs30
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait.rs24
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait2.rs25
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait3.rs24
-rw-r--r--src/test/ui/impl-trait/nested-return-type3.rs20
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.rs2
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.stderr32
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr35
-rw-r--r--src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr159
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr2
-rw-r--r--src/test/ui/impl-trait/projection.rs29
-rw-r--r--src/test/ui/impl-trait/question_mark.rs30
-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-2.rs17
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr11
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs30
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr25
-rw-r--r--src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs19
-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/trait_resolution.rs30
-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.stderr27
-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.rs1
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.stderr15
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.rs7
-rw-r--r--src/test/ui/impl-trait/where-allowed-2.stderr13
-rw-r--r--src/test/ui/issues-71798.rs4
-rw-r--r--src/test/ui/issues-71798.stderr18
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches.rs14
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches.stderr16
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches2.rs28
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs46
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs27
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs7
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/nested.rs23
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs10
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion.rs23
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion2.rs21
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr16
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion3.rs21
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr19
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion4.rs23
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr29
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs16
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs3
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr13
-rw-r--r--src/test/ui/lint/inline-trait-and-foreign-items.rs2
-rw-r--r--src/test/ui/lint/inline-trait-and-foreign-items.stderr4
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-2.rs2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-2.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-3.rs2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-3.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-5.rs2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-5.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-1.rs2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-1.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-2.rs2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-2.stderr2
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.rs2
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.stderr2
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.rs7
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.stderr12
-rw-r--r--src/test/ui/never_type/impl_trait_fallback.rs10
-rw-r--r--src/test/ui/never_type/impl_trait_fallback2.rs21
-rw-r--r--src/test/ui/never_type/impl_trait_fallback2.stderr9
-rw-r--r--src/test/ui/never_type/impl_trait_fallback3.rs15
-rw-r--r--src/test/ui/never_type/impl_trait_fallback3.stderr10
-rw-r--r--src/test/ui/never_type/impl_trait_fallback4.rs24
-rw-r--r--src/test/ui/never_type/impl_trait_fallback4.stderr9
-rw-r--r--src/test/ui/nll/issue-52113.rs4
-rw-r--r--src/test/ui/nll/issue-52113.stderr6
-rw-r--r--src/test/ui/nll/issue-73159-rpit-static.rs2
-rw-r--r--src/test/ui/nll/issue-73159-rpit-static.stderr5
-rw-r--r--src/test/ui/nll/relate_tys/opaque-hrtb.rs16
-rw-r--r--src/test/ui/nll/relate_tys/opaque-hrtb.stderr11
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-captures.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-captures.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-outlives.rs4
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr12
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.rs9
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr182
-rw-r--r--src/test/ui/polymorphization/generators.rs2
-rw-r--r--src/test/ui/polymorphization/generators.stderr20
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs2
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr23
-rw-r--r--src/test/ui/save-analysis/issue-68621.rs2
-rw-r--r--src/test/ui/save-analysis/issue-68621.stderr4
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr4
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr4
-rw-r--r--src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs1
-rw-r--r--src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr12
-rw-r--r--src/test/ui/suggestions/issue-81098.rs2
-rw-r--r--src/test/ui/suggestions/issue-81098.stderr31
-rw-r--r--src/test/ui/traits/alias/issue-83613.rs2
-rw-r--r--src/test/ui/traits/alias/issue-83613.stderr4
-rw-r--r--src/test/ui/traits/pointee-tail-is-generic-errors.rs2
-rw-r--r--src/test/ui/traits/pointee-tail-is-generic-errors.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/argument-types.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/argument-types.stderr17
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/bounds-are-checked.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr21
-rw-r--r--src/test/ui/type-alias-impl-trait/closures_in_branches.rs31
-rw-r--r--src/test/ui/type-alias-impl-trait/closures_in_branches.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr26
-rw-r--r--src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/fallback.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/field-types.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/field-types.stderr21
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr38
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr26
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr38
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_not_used.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_not_used.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr36
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr29
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.stderr36
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53598.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53598.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr34
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57700.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57700.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-58951-2.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60371.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60371.stderr13
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.stderr37
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63355.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63355.stderr19
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-74280.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-77179.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-93411.rs19
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs13
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr7
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr23
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs17
-rw-r--r--src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/nested.rs17
-rw-r--r--src/test/ui/type-alias-impl-trait/nested.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr19
-rw-r--r--src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr24
-rw-r--r--src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/not_a_defining_use.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr26
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.rs26
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.stderr51
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-2.rs10
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-2.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-3.rs14
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-4.rs25
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential-4.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential.rs25
-rw-r--r--src/test/ui/type-alias-impl-trait/self-referential.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/static-const-types.rs8
-rw-r--r--src/test/ui/type-alias-impl-trait/static-const-types.stderr33
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr21
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs84
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let.rs11
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let.stderr76
353 files changed, 3876 insertions, 1552 deletions
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 4124eada188..31564a0cbd5 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -305,7 +305,7 @@ pub fn return_impl_trait() -> i32        {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
 #[rustc_clean(cfg = "cfail3")]
 #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
 #[rustc_clean(cfg = "cfail6")]
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
index 4c36289f47b..67b97c21805 100644
--- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
@@ -30,7 +30,7 @@ impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
 
     fn func() -> Self::Out {
-        //~^ ERROR the trait bound `String: Copy` is not satisfied
         Box::new(AssocNoCopy)
+        //~^ ERROR the trait bound `String: Copy` is not satisfied
     }
 }
diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
index a32ab453152..f1dcd34066d 100644
--- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
+++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
+  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:33:9
    |
-LL |     fn func() -> Self::Out {
-   |                  ^^^^^^^^^ the trait `Copy` is not implemented for `String`
+LL |         Box::new(AssocNoCopy)
+   |         ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = note: required for the cast to the object type `dyn Bar<Assoc = <AssocNoCopy as Thing>::Out::{opaque#0}>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs
index 5f994f26534..ef0443034ec 100644
--- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs
+++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.rs
@@ -23,7 +23,8 @@ fn bar() -> impl Bar {
 }
 
 fn baz() -> impl Bar<Item = i32> {
-//~^ ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
+    //~^ ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
+    //~| ERROR type mismatch resolving `<impl Bar as Foo>::Item == i32`
     bar()
 }
 
diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
index 283ecea735d..b7c49570ca4 100644
--- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
+++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
@@ -2,18 +2,43 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
   --> $DIR/impl-trait-return-missing-constraint.rs:25:13
    |
 LL | fn bar() -> impl Bar {
-   |             -------- the found opaque type
+   |             -------- the expected opaque type
 ...
 LL | fn baz() -> impl Bar<Item = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
+   |             ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32`
    |
-   = note:         expected type `i32`
-           found associated type `<impl Bar as Foo>::Item`
+   = note: expected associated type `<impl Bar as Foo>::Item`
+                         found type `i32`
+   = help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` or calling a method that returns `<impl Bar as Foo>::Item`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
    |
 LL | fn bar() -> impl Bar<Item = i32> {
    |                     ++++++++++++
 
-error: aborting due to previous error
+error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
+  --> $DIR/impl-trait-return-missing-constraint.rs:25:34
+   |
+LL |   fn bar() -> impl Bar {
+   |               -------- the expected opaque type
+...
+LL |   fn baz() -> impl Bar<Item = i32> {
+   |  __________________________________^
+LL | |
+LL | |
+LL | |     bar()
+LL | | }
+   | |_^ expected associated type, found `i32`
+   |
+   = note: expected associated type `<impl Bar as Foo>::Item`
+                         found type `i32`
+   = help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` or calling a method that returns `<impl Bar as Foo>::Item`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
+   |
+LL | fn bar() -> impl Bar<Item = i32> {
+   |                     ++++++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
index 44d60c1d80d..f21c8115124 100644
--- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
+++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
@@ -8,10 +8,10 @@ LL |     Box::new(async { x } )
    |                    may outlive borrowed value `x`
    |
 note: async block is returned here
-  --> $DIR/async-borrowck-escaping-block-error.rs:4:20
+  --> $DIR/async-borrowck-escaping-block-error.rs:6:5
    |
-LL | fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     Box::new(async { x } )
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
    |
 LL |     Box::new(async move { x } )
diff --git a/src/test/ui/async-await/issue-70818.rs b/src/test/ui/async-await/issue-70818.rs
index 0609e4fc081..019c56eb2fa 100644
--- a/src/test/ui/async-await/issue-70818.rs
+++ b/src/test/ui/async-await/issue-70818.rs
@@ -2,7 +2,7 @@
 
 use std::future::Future;
 fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
-//~^ Error future cannot be sent between threads safely
+    //~^ Error future cannot be sent between threads safely
     async { (ty, ty1) }
 }
 
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
index 2722c72c20a..cdb141c0e3e 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
@@ -14,12 +14,16 @@ LL | | }
    = help: consider adding the following bound: `'a: 'b`
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ret-impl-trait-one.rs:16:65
+  --> $DIR/ret-impl-trait-one.rs:16:80
    |
-LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |                                    --                           ^^^^^^^^^^^^^^
-   |                                    |
-   |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |  ____________________________________--__________________________________________^
+   | |                                    |
+   | |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index 149692a2c69..2eb3a07059f 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -1,19 +1,26 @@
 error[E0623]: lifetime mismatch
-  --> $DIR/ret-impl-trait-one.rs:10:65
+  --> $DIR/ret-impl-trait-one.rs:10:85
    |
-LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
-   |                                                      ------     ^^^^^^^^^^^^^^^^^^^
-   |                                                      |          |
-   |                                                      |          ...but data from `a` is returned here
-   |                                                      this parameter and the return type are declared with different lifetimes...
+LL |   async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
+   |  ______________________________________________________------_____-------------------_^
+   | |                                                      |
+   | |                                                      this parameter and the return type are declared with different lifetimes...
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^ ...but data from `a` is returned here
 
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/ret-impl-trait-one.rs:16:65
+  --> $DIR/ret-impl-trait-one.rs:16:80
    |
-LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |                                    --                           ^^^^^^^^^^^^^^
-   |                                    |
-   |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |  ____________________________________--__________________________________________^
+   | |                                    |
+   | |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^
    |
 help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
    |
diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs
index b3c59734e03..cfb0ef1b33a 100644
--- a/src/test/ui/async-await/no-const-async.rs
+++ b/src/test/ui/async-await/no-const-async.rs
@@ -3,3 +3,4 @@
 
 pub const async fn x() {}
 //~^ ERROR functions cannot be both `const` and `async`
+//~| ERROR cycle detected
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index 90ec646c8c0..fd76c282f96 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -7,5 +7,36 @@ LL | pub const async fn x() {}
    |     |     `async` because of this
    |     `const` because of this
 
-error: aborting due to previous error
+error[E0391]: cycle detected when computing type of `x::{opaque#0}`
+  --> $DIR/no-const-async.rs:4:24
+   |
+LL | pub const async fn x() {}
+   |                        ^
+   |
+note: ...which requires borrow-checking `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `x`...
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/no-const-async.rs:4:1
+   |
+LL | pub const async fn x() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs
index aa773319458..edc4cb8ac5d 100644
--- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs
+++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs
@@ -2,7 +2,8 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden when using `async` and `await`.
 
-async fn recursive_async_function() -> () { //~ ERROR
+async fn recursive_async_function() -> () {
+    //~^ ERROR recursion in an `async fn` requires boxing
     recursive_async_function().await;
 }
 
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index c7c5b51e733..796f82e779c 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -21,8 +21,8 @@ async fn dummy() {}
 async fn suggest_await_in_async_fn_return() {
     dummy()
     //~^ ERROR mismatched types [E0308]
-    //~| HELP consider using a semicolon here
     //~| HELP consider `await`ing on the `Future`
+    //~| HELP consider using a semicolon here
     //~| SUGGESTION .await
 }
 
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index 3d62f059f37..78d78f57955 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -29,10 +29,13 @@ LL |     T: Generator<ResumeTy, Yield = ()>,
    |                            ^^^^^^^^^^ required by this bound in `from_generator`
 
 error[E0280]: the requirement `<impl Future as Future>::Output == u32` is not satisfied
-  --> $DIR/async.rs:7:25
+  --> $DIR/async.rs:7:29
    |
-LL | async fn foo(x: u32) -> u32 {
-   |                         ^^^
+LL |   async fn foo(x: u32) -> u32 {
+   |  _____________________________^
+LL | |     x
+LL | | }
+   | |_^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr
index bb00465758a..46379a3815a 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr
@@ -8,10 +8,10 @@ LL |        println!("{:?}", p);
    |                         - `p` is borrowed here
    |
 note: closure is returned here
-  --> $DIR/borrowck-4.rs:8:14
+  --> $DIR/borrowck-4.rs:15:5
    |
-LL | fn foo () -> impl FnMut()->() {
-   |              ^^^^^^^^^^^^^^^^
+LL |     c
+   |     ^
 help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword
    |
 LL |     let mut c = move || {
diff --git a/src/test/ui/conservative_impl_trait.rs b/src/test/ui/conservative_impl_trait.rs
index b7f795eadb7..b8488d83998 100644
--- a/src/test/ui/conservative_impl_trait.rs
+++ b/src/test/ui/conservative_impl_trait.rs
@@ -2,6 +2,7 @@
 
 fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
     //~^ ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
 }
 
 fn main() {}
diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr
index 63a4df242f8..2348f2f5297 100644
--- a/src/test/ui/conservative_impl_trait.stderr
+++ b/src/test/ui/conservative_impl_trait.stderr
@@ -6,6 +6,18 @@ LL | fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
    |
    = help: the trait `Iterator` is not implemented for `()`
 
-error: aborting due to previous error
+error[E0277]: `()` is not an iterator
+  --> $DIR/conservative_impl_trait.rs:3:60
+   |
+LL |   fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
+   |  ____________________________________________________________^
+LL | |
+LL | |
+LL | | }
+   | |_^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs
index 308c121a941..24031aa1e61 100644
--- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs
+++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.rs
@@ -5,6 +5,7 @@ impl<const N: u32> Trait for Uwu<N> {}
 
 fn rawr() -> impl Trait {
     //~^ error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
+    //~| error: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
     Uwu::<10, 12>
 }
 
@@ -16,11 +17,13 @@ impl Traitor<1, 2> for u64 {}
 
 fn uwu<const N: u8>() -> impl Traitor<N> {
     //~^ error: the trait bound `u32: Traitor<N, N>` is not satisfied
+    //~| error: the trait bound `u32: Traitor<N, N>` is not satisfied
     1_u32
 }
 
 fn owo() -> impl Traitor {
     //~^ error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
+    //~| error: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
     1_u64
 }
 
diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
index 19813a491c9..81cfcb35606 100644
--- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
+++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
@@ -7,8 +7,22 @@ LL | fn rawr() -> impl Trait {
    = help: the following implementations were found:
              <Uwu<N> as Trait>
 
+error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
+  --> $DIR/rp_impl_trait_fail.rs:6:25
+   |
+LL |   fn rawr() -> impl Trait {
+   |  _________________________^
+LL | |
+LL | |
+LL | |     Uwu::<10, 12>
+LL | | }
+   | |_^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>`
+   |
+   = help: the following implementations were found:
+             <Uwu<N> as Trait>
+
 error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied
-  --> $DIR/rp_impl_trait_fail.rs:17:26
+  --> $DIR/rp_impl_trait_fail.rs:18:26
    |
 LL | fn uwu<const N: u8>() -> impl Traitor<N> {
    |                          ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32`
@@ -17,8 +31,23 @@ LL | fn uwu<const N: u8>() -> impl Traitor<N> {
              <u32 as Traitor<N, 2_u8>>
              <u64 as Traitor<1_u8, 2_u8>>
 
+error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied
+  --> $DIR/rp_impl_trait_fail.rs:18:42
+   |
+LL |   fn uwu<const N: u8>() -> impl Traitor<N> {
+   |  __________________________________________^
+LL | |
+LL | |
+LL | |     1_u32
+LL | | }
+   | |_^ the trait `Traitor<N, N>` is not implemented for `u32`
+   |
+   = help: the following implementations were found:
+             <u32 as Traitor<N, 2_u8>>
+             <u64 as Traitor<1_u8, 2_u8>>
+
 error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
-  --> $DIR/rp_impl_trait_fail.rs:22:13
+  --> $DIR/rp_impl_trait_fail.rs:24:13
    |
 LL | fn owo() -> impl Traitor {
    |             ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64`
@@ -27,6 +56,21 @@ LL | fn owo() -> impl Traitor {
              <u64 as Traitor<1_u8, 2_u8>>
              <u32 as Traitor<N, 2_u8>>
 
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied
+  --> $DIR/rp_impl_trait_fail.rs:24:26
+   |
+LL |   fn owo() -> impl Traitor {
+   |  __________________________^
+LL | |
+LL | |
+LL | |     1_u64
+LL | | }
+   | |_^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64`
+   |
+   = help: the following implementations were found:
+             <u64 as Traitor<1_u8, 2_u8>>
+             <u32 as Traitor<N, 2_u8>>
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
index dab9c687e24..405d6e2a9f5 100644
--- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
+++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
@@ -3,11 +3,9 @@
 #![allow(incomplete_features)]
 pub mod foo {
     type MainFn = impl Fn();
-    //~^ ERROR could not find defining uses
 
     fn bar() {}
     pub const BAR: MainFn = bar;
-    //~^ ERROR mismatched types [E0308]
 }
 
 use foo::BAR as main; //~ ERROR `main` function not found in crate
diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
index b9bc0262a56..fabb6ffb02f 100644
--- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
+++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
@@ -1,30 +1,11 @@
 error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden`
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:13:22
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:11:22
    |
 LL | use foo::BAR as main;
    |     ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs`
    |     |
    |     non-function item at `crate::main` is found
 
-error[E0308]: mismatched types
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:9:29
-   |
-LL |     type MainFn = impl Fn();
-   |                   --------- the expected opaque type
-...
-LL |     pub const BAR: MainFn = bar;
-   |                             ^^^ expected opaque type, found fn item
-   |
-   = note: expected opaque type `impl Fn()`
-                  found fn item `fn() {bar}`
-
-error: could not find defining uses
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:5:19
-   |
-LL |     type MainFn = impl Fn();
-   |                   ^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0601.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index ea82837d4bf..6dfd7f6840f 100644
--- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -1,13 +1,13 @@
 // ignore-compare-mode-chalk
+// check-pass
 #![feature(type_alias_impl_trait)]
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR could not find defining uses
 
 struct Bar(Foo);
 fn define() -> Bar {
-    Bar(42) //~ ERROR mismatched types
+    Bar(42)
 }
 
 type Foo2 = impl Debug;
@@ -17,21 +17,18 @@ fn define2() {
 }
 
 type Foo3 = impl Debug;
-//~^ ERROR could not find defining uses
 
 fn define3(x: Foo3) {
-    let y: i32 = x; //~ ERROR mismatched types
+    let y: i32 = x;
 }
 fn define3_1() {
-    define3(42) //~ ERROR mismatched types
+    define3(42)
 }
 
 type Foo4 = impl Debug;
-//~^ ERROR could not find defining uses
 
 fn define4() {
     let y: Foo4 = 42;
-    //~^ ERROR mismatched types [E0308]
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
deleted file mode 100644
index da3ddb1c509..00000000000
--- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
+++ /dev/null
@@ -1,73 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:10:9
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     Bar(42)
-   |         ^^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:23:18
-   |
-LL | type Foo3 = impl Debug;
-   |             ---------- the found opaque type
-...
-LL |     let y: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-   |
-   = note:     expected type `i32`
-           found opaque type `impl Debug`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:26:13
-   |
-LL | type Foo3 = impl Debug;
-   |             ---------- the expected opaque type
-...
-LL |     define3(42)
-   |             ^^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:33:19
-   |
-LL | type Foo4 = impl Debug;
-   |             ---------- the expected opaque type
-...
-LL |     let y: Foo4 = 42;
-   |            ----   ^^ expected opaque type, found integer
-   |            |
-   |            expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:19:13
-   |
-LL | type Foo3 = impl Debug;
-   |             ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13
-   |
-LL | type Foo4 = impl Debug;
-   |             ^^^^^^^^^^
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs
index ce9159b53e0..f27956e4595 100644
--- a/src/test/ui/generator/issue-88653.rs
+++ b/src/test/ui/generator/issue-88653.rs
@@ -6,10 +6,14 @@
 use std::ops::Generator;
 
 fn foo(bar: bool) -> impl Generator<(bool,)> {
-//~^ ERROR: type mismatch in generator arguments [E0631]
-//~| NOTE: expected signature of `fn((bool,)) -> _`
+    //~^ ERROR: type mismatch in generator arguments [E0631]
+    //~| ERROR: type mismatch in generator arguments [E0631]
+    //~| NOTE: expected signature of `fn((bool,)) -> _`
+    //~| NOTE: expected signature of `fn((bool,)) -> _`
+    //~| NOTE: in this expansion of desugaring of `impl Trait`
     |bar| {
-    //~^ NOTE: found signature of `fn(bool) -> _`
+        //~^ NOTE: found signature of `fn(bool) -> _`
+        //~| NOTE: found signature of `fn(bool) -> _`
         if bar {
             yield bar;
         }
diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr
index 5bd8ad129fe..25357411ce1 100644
--- a/src/test/ui/generator/issue-88653.stderr
+++ b/src/test/ui/generator/issue-88653.stderr
@@ -7,6 +7,22 @@ LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
 LL |     |bar| {
    |     ----- found signature of `fn(bool) -> _`
 
-error: aborting due to previous error
+error[E0631]: type mismatch in generator arguments
+  --> $DIR/issue-88653.rs:8:46
+   |
+LL |   fn foo(bar: bool) -> impl Generator<(bool,)> {
+   |  ______________________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     |bar| {
+   | |     ----- found signature of `fn(bool) -> _`
+...  |
+LL | |     }
+LL | | }
+   | |_^ expected signature of `fn((bool,)) -> _`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.rs b/src/test/ui/generator/type-mismatch-signature-deduction.rs
index 7774ff48f56..77b830783c3 100644
--- a/src/test/ui/generator/type-mismatch-signature-deduction.rs
+++ b/src/test/ui/generator/type-mismatch-signature-deduction.rs
@@ -2,7 +2,9 @@
 
 use std::ops::Generator;
 
-fn foo() -> impl Generator<Return = i32> { //~ ERROR type mismatch
+fn foo() -> impl Generator<Return = i32> {
+    //~^ ERROR type mismatch
+    //~| ERROR type mismatch
     || {
         if false {
             return Ok(6);
diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
index 3f1f33a3b12..6369e7ec4c7 100644
--- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr
+++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch-signature-deduction.rs:13:9
+  --> $DIR/type-mismatch-signature-deduction.rs:15:9
    |
 LL |         5
    |         ^ expected enum `Result`, found integer
@@ -7,21 +7,37 @@ LL |         5
    = note: expected type `Result<{integer}, _>`
               found type `{integer}`
 note: return type inferred to be `Result<{integer}, _>` here
-  --> $DIR/type-mismatch-signature-deduction.rs:8:20
+  --> $DIR/type-mismatch-signature-deduction.rs:10:20
    |
 LL |             return Ok(6);
    |                    ^^^^^
 
-error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6] as Generator>::Return == i32`
+error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:8:5: 16:6] as Generator>::Return == i32`
   --> $DIR/type-mismatch-signature-deduction.rs:5:13
    |
 LL | fn foo() -> impl Generator<Return = i32> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32`
    |
-   = note: expected type `i32`
-              found enum `Result<{integer}, _>`
+   = note: expected enum `Result<{integer}, _>`
+              found type `i32`
 
-error: aborting due to 2 previous errors
+error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:8:5: 16:6] as Generator>::Return == i32`
+  --> $DIR/type-mismatch-signature-deduction.rs:5:42
+   |
+LL |   fn foo() -> impl Generator<Return = i32> {
+   |  __________________________________________^
+LL | |
+LL | |
+LL | |     || {
+...  |
+LL | |     }
+LL | | }
+   | |_^ expected enum `Result`, found `i32`
+   |
+   = note: expected enum `Result<{integer}, _>`
+              found type `i32`
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0271, E0308.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
index 98a5f4254bb..fbf1c8f95fe 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
@@ -1,4 +1,4 @@
-error[E0477]: the type `impl Stream<Item = i32>` does not fulfill the required lifetime
+error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime
   --> $DIR/issue-86218.rs:23:28
    |
 LL |     type InnerStream<'s> = impl Stream<Item = i32> + 's;
@@ -10,6 +10,14 @@ note: type must outlive the lifetime `'s` as defined here as required by this bi
 LL |     type InnerStream<'s> = impl Stream<Item = i32> + 's;
    |                      ^^
 
-error: aborting due to previous error
+error: unconstrained opaque type
+  --> $DIR/issue-86218.rs:23:28
+   |
+LL |     type InnerStream<'s> = impl Stream<Item = i32> + 's;
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `InnerStream` must be used in combination with a concrete type within the same module
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
index 3e607d4004e..5cbadfacc1b 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
@@ -1,21 +1,19 @@
-error[E0271]: type mismatch resolving `<impl Future as Future>::Output == impl Stream<Item = Repr>`
-  --> $DIR/issue-89008.rs:39:43
+error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
+  --> $DIR/issue-89008.rs:40:9
    |
-LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
-   |                                 ------------------------ the expected opaque type
-...
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found struct `Empty`
+   |                        ---- this type parameter
+LL |         async {empty()}
+   |         ^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
    |
-   = note: expected opaque type `impl Stream<Item = Repr>`
-                   found struct `Empty<_>`
-
-error: could not find defining uses
-  --> $DIR/issue-89008.rs:35:33
+note: expected this to be `()`
+  --> $DIR/issue-89008.rs:18:17
    |
-LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     type Item = ();
+   |                 ^^
+   = note:   expected unit type `()`
+           found type parameter `Repr`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs
index d9d17751fa6..c65f3fb2aa0 100644
--- a/src/test/ui/generic-associated-types/issue-87258_a.rs
+++ b/src/test/ui/generic-associated-types/issue-87258_a.rs
@@ -16,7 +16,8 @@ pub trait Trait2 {
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = impl Trait1;
-    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+    //~^ ERROR unconstrained opaque type
+    fn foo<'a>() -> Self::FooFuture<'a> {
         Struct(unimplemented!())
     }
 }
diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr
index 93513a4563f..db3a5c819cb 100644
--- a/src/test/ui/generic-associated-types/issue-87258_a.stderr
+++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr
@@ -1,11 +1,10 @@
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-87258_a.rs:19:21
+error: unconstrained opaque type
+  --> $DIR/issue-87258_a.rs:18:26
    |
-LL |     fn foo<'a>() -> Self::FooFuture<'a> {
-   |                     ^^^^^^^^^^^^^^^^^^^
+LL |     type FooFuture<'a> = impl Trait1;
+   |                          ^^^^^^^^^^^
    |
-   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+   = note: `FooFuture` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs
index b29a978f517..f59e0d76659 100644
--- a/src/test/ui/generic-associated-types/issue-87258_b.rs
+++ b/src/test/ui/generic-associated-types/issue-87258_b.rs
@@ -15,10 +15,11 @@ pub trait Trait2 {
 }
 
 type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
+//~^ ERROR unconstrained opaque type
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = Helper<'c, 'a, S>;
-    fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR
+    fn foo<'a>() -> Self::FooFuture<'a> {
         Struct(unimplemented!())
     }
 }
diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr
index e077a423400..9faccc96124 100644
--- a/src/test/ui/generic-associated-types/issue-87258_b.stderr
+++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr
@@ -1,11 +1,10 @@
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-87258_b.rs:21:21
+error: unconstrained opaque type
+  --> $DIR/issue-87258_b.rs:17:49
    |
-LL |     fn foo<'a>() -> Self::FooFuture<'a> {
-   |                     ^^^^^^^^^^^^^^^^^^^
+LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
+   |                                                 ^^^^^^^^^^^
    |
-   = note: hidden type `Struct<'_>` captures lifetime '_#7r
+   = note: `Helper` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs
index c97d17811ba..e0796dfecbb 100644
--- a/src/test/ui/generic-associated-types/issue-88595.rs
+++ b/src/test/ui/generic-associated-types/issue-88595.rs
@@ -17,7 +17,6 @@ struct C;
 
 impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
-    //~^ ERROR: could not find defining uses
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
 }
diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr
index 4e4f86bbac8..79d3479af8c 100644
--- a/src/test/ui/generic-associated-types/issue-88595.stderr
+++ b/src/test/ui/generic-associated-types/issue-88595.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-88595.rs:22:23
+  --> $DIR/issue-88595.rs:21:35
    |
 LL |     fn a(&'a self) -> Self::B<'a> {}
-   |                       ^^^^^^^^^^^
+   |                                   ^^
    |
 note: lifetime used multiple times
   --> $DIR/issue-88595.rs:18:6
@@ -12,11 +12,5 @@ LL | impl<'a> A<'a> for C {
 LL |     type B<'b> = impl Clone;
    |            ^^
 
-error: could not find defining uses
-  --> $DIR/issue-88595.rs:19:18
-   |
-LL |     type B<'b> = impl Clone;
-   |                  ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/async_scope_creep.rs b/src/test/ui/impl-trait/async_scope_creep.rs
new file mode 100644
index 00000000000..7a9d64d339f
--- /dev/null
+++ b/src/test/ui/impl-trait/async_scope_creep.rs
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+// edition:2021
+// check-pass
+
+struct Pending {}
+
+struct CantOpen {}
+
+trait AsyncRead {}
+
+impl AsyncRead for i32 {}
+
+type PendingReader<'a> = impl AsyncRead + 'a;
+
+type OpeningReadFuture<'a> =
+    impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
+
+impl Pending {
+    async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
+        Ok(42)
+    }
+
+    fn read_fut(&mut self) -> OpeningReadFuture<'_> {
+        self.read()
+    }
+}
+
+fn main() {}
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/autoderef.rs b/src/test/ui/impl-trait/autoderef.rs
new file mode 100644
index 00000000000..5e4f4995447
--- /dev/null
+++ b/src/test/ui/impl-trait/autoderef.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+use std::path::Path;
+use std::ffi::OsStr;
+use std::ops::Deref;
+
+fn frob(path: &str) -> impl Deref<Target = Path> + '_ {
+    OsStr::new(path).as_ref()
+}
+
+fn open_parent<'path>(_path: &'path Path) {
+    todo!()
+}
+
+fn main() {
+    let old_path = frob("hello");
+
+    open_parent(&old_path);
+}
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs
index 8ec06e534d1..9f962fa9bba 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.rs
+++ b/src/test/ui/impl-trait/bound-normalization-fail.rs
@@ -24,6 +24,7 @@ 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
+        //~| ERROR: type mismatch
         Foo(())
     }
 }
@@ -39,8 +40,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
+        //~| ERROR: type mismatch
+        //~| ERROR: type mismatch
         Foo(())
     }
 }
diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr
index afa21c1a858..0344f416eb7 100644
--- a/src/test/ui/impl-trait/bound-normalization-fail.stderr
+++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr
@@ -4,43 +4,90 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as imp
 LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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> {
+   |                         ++++++++++++
+
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+  --> $DIR/bound-normalization-fail.rs:25:64
+   |
+LL |       fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
+   |  ________________________________________________________________^
+LL | |
+LL | |
+LL | |         Foo(())
+LL | |     }
+   | |_____^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
+   |
+note: expected this to be `()`
+  --> $DIR/bound-normalization-fail.rs:14:19
+   |
+LL |     type Output = T;
+   |                   ^
+   = 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> {
    |                         ++++++++++++
 
 error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
-  --> $DIR/bound-normalization-fail.rs:41:41
+  --> $DIR/bound-normalization-fail.rs:42:41
    |
 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:42:41
    |
 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`
    |
-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 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> {
+   |                                 ++++++++++++
+
+error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
+  --> $DIR/bound-normalization-fail.rs:42:73
+   |
+LL |       fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
+   |  _________________________________________________________________________^
+LL | |
+LL | |
+LL | |
+LL | |         Foo(())
+LL | |     }
+   | |_____^ type mismatch resolving `<Foo<()> as FooLike>::Output == <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> {
    |                                 ++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0271, E0760.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs
new file mode 100644
index 00000000000..c27b5ca9f66
--- /dev/null
+++ b/src/test/ui/impl-trait/cross-return-site-inference.rs
@@ -0,0 +1,45 @@
+// edition:2021
+
+fn foo(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return vec![42]
+    }
+    [].into_iter().collect()
+}
+
+fn bar(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return [].into_iter().collect()
+    }
+    vec![42]
+}
+
+fn bak(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return std::iter::empty().collect()
+    }
+    vec![42]
+}
+
+fn baa(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return [42].into_iter().collect()
+    }
+    vec![]
+}
+
+fn muh() -> Result<(), impl std::fmt::Debug> {
+    Err("whoops")?; //~ ERROR `?` couldn't convert the error to `impl Debug`
+    Ok(())
+}
+
+fn muh2() -> Result<(), impl std::fmt::Debug> {
+    return Err(From::from("foo")); //~ ERROR the trait bound `impl Debug: From<&str>` is not satisfied
+    Ok(())
+}
+
+fn muh3() -> Result<(), impl std::fmt::Debug> {
+    Err(From::from("foo")) //~ ERROR the trait bound `impl Debug: From<&str>` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr
new file mode 100644
index 00000000000..06afb938c5f
--- /dev/null
+++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr
@@ -0,0 +1,26 @@
+error[E0277]: `?` couldn't convert the error to `impl Debug`
+  --> $DIR/cross-return-site-inference.rs:32:18
+   |
+LL | fn muh() -> Result<(), impl std::fmt::Debug> {
+   |             -------------------------------- expected `impl Debug` because of this
+LL |     Err("whoops")?;
+   |                  ^ the trait `From<&str>` is not implemented for `impl Debug`
+   |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<(), impl Debug>`
+
+error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied
+  --> $DIR/cross-return-site-inference.rs:37:16
+   |
+LL |     return Err(From::from("foo"));
+   |                ^^^^^^^^^^ the trait `From<&str>` is not implemented for `impl Debug`
+
+error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied
+  --> $DIR/cross-return-site-inference.rs:42:9
+   |
+LL |     Err(From::from("foo"))
+   |         ^^^^^^^^^^ the trait `From<&str>` is not implemented for `impl Debug`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/divergence.rs b/src/test/ui/impl-trait/divergence.rs
new file mode 100644
index 00000000000..211f7972dbc
--- /dev/null
+++ b/src/test/ui/impl-trait/divergence.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/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..804ccbcc6c0 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -12,19 +12,10 @@ 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 |     }
+   |                    -------- expected `_` because of return 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
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
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..7876add5aa6
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs
@@ -0,0 +1,45 @@
+// 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
+
+#![feature(type_alias_impl_trait)]
+
+fn reify_as() -> Thunk<impl FnOnce(Continuation) -> Continuation> {
+    Thunk::new(|mut cont| { //~ ERROR type annotations needed
+        cont.reify_as();
+        cont
+    })
+}
+
+type Tait = impl FnOnce(Continuation) -> Continuation;
+
+fn reify_as_tait() -> Thunk<Tait> {
+    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..dcf1982312f
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr
@@ -0,0 +1,19 @@
+error[E0282]: type annotations needed
+  --> $DIR/hidden-type-is-opaque-2.rs:8:17
+   |
+LL |     Thunk::new(|mut cont| {
+   |                 ^^^^^^^^ consider giving this closure parameter a type
+   |
+   = note: type must be known at this point
+
+error[E0282]: type annotations needed
+  --> $DIR/hidden-type-is-opaque-2.rs:17: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 2 previous errors
+
+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..72b4028d854
--- /dev/null
+++ b/src/test/ui/impl-trait/hidden-type-is-opaque.rs
@@ -0,0 +1,42 @@
+// check-pass
+#![feature(type_alias_impl_trait)]
+
+fn reify_as() -> Thunk<impl ContFn> {
+    Thunk::new(|mut cont| {
+        cont.reify_as();
+        cont
+    })
+}
+
+type Tait = impl ContFn;
+
+fn reify_as_tait() -> Thunk<Tait> {
+    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/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
index a6976daff01..a79bb6474d8 100644
--- a/src/test/ui/impl-trait/issue-86465.rs
+++ b/src/test/ui/impl-trait/issue-86465.rs
@@ -3,8 +3,8 @@
 type X<'a, 'b> = impl std::fmt::Debug;
 
 fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
-    //~^ ERROR concrete type differs from previous defining opaque type use
     (a, a)
+    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr
index 595b16aa685..90d6904ed61 100644
--- a/src/test/ui/impl-trait/issue-86465.stderr
+++ b/src/test/ui/impl-trait/issue-86465.stderr
@@ -1,14 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-86465.rs:5:1
+  --> $DIR/issue-86465.rs:6:5
    |
-LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32`
-   |
-note: previous use here
-  --> $DIR/issue-86465.rs:5:1
-   |
-LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (a, a)
+   |     ^^^^^^
+   |     |
+   |     expected `&'a u32`, got `&'b u32`
+   |     this expression supplies two conflicting concrete types for the same opaque type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs
new file mode 100644
index 00000000000..a70166e03a7
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54895.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+trait Trait<'a> {
+    type Out;
+    fn call(&'a self) -> Self::Out;
+}
+
+struct X(());
+
+impl<'a> Trait<'a> for X {
+    type Out = ();
+    fn call(&'a self) -> Self::Out {
+        ()
+    }
+}
+
+fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+    X(())
+}
+
+fn main() {
+    let _ = f();
+}
diff --git a/src/test/ui/impl-trait/issues/issue-62742.rs b/src/test/ui/impl-trait/issues/issue-62742.rs
new file mode 100644
index 00000000000..041bd0e3855
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-62742.rs
@@ -0,0 +1,32 @@
+use std::marker::PhantomData;
+
+fn _alias_check() {
+    WrongImpl::foo(0i32);
+    //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
+    WrongImpl::<()>::foo(0i32);
+    //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
+    //~| ERROR trait bounds were not satisfied
+    CorrectImpl::foo(0i32);
+}
+
+pub trait Raw<T: ?Sized> {
+    type Value;
+}
+
+pub type WrongImpl<T> = SafeImpl<T, RawImpl<T>>;
+
+pub type CorrectImpl<T> = SafeImpl<[T], RawImpl<T>>;
+
+pub struct RawImpl<T>(PhantomData<T>);
+
+impl<T> Raw<[T]> for RawImpl<T> {
+    type Value = T;
+}
+
+pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+
+impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
+    pub fn foo(value: A::Value) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr
new file mode 100644
index 00000000000..28068b7548c
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-62742.stderr
@@ -0,0 +1,54 @@
+error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
+  --> $DIR/issue-62742.rs:4:5
+   |
+LL |     WrongImpl::foo(0i32);
+   |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
+   |
+   = help: the following implementations were found:
+             <RawImpl<T> as Raw<[T]>>
+note: required by a bound in `SafeImpl`
+  --> $DIR/issue-62742.rs:26:35
+   |
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+   |                                   ^^^^^^ required by this bound in `SafeImpl`
+
+error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-62742.rs:6:22
+   |
+LL |     WrongImpl::<()>::foo(0i32);
+   |                      ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
+...
+LL | pub struct RawImpl<T>(PhantomData<T>);
+   | -------------------------------------- doesn't satisfy `RawImpl<()>: Raw<()>`
+...
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+   | --------------------------------------------------------------- function or associated item `foo` not found for this
+   |
+   = note: the following trait bounds were not satisfied:
+           `RawImpl<()>: Raw<()>`
+note: the following trait must be implemented
+  --> $DIR/issue-62742.rs:12:1
+   |
+LL | / pub trait Raw<T: ?Sized> {
+LL | |     type Value;
+LL | | }
+   | |_^
+
+error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
+  --> $DIR/issue-62742.rs:6:5
+   |
+LL |     WrongImpl::<()>::foo(0i32);
+   |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
+   |
+   = help: the following implementations were found:
+             <RawImpl<T> as Raw<[T]>>
+note: required by a bound in `SafeImpl`
+  --> $DIR/issue-62742.rs:26:35
+   |
+LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
+   |                                   ^^^^^^ required by this bound in `SafeImpl`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr
new file mode 100644
index 00000000000..17fbe046e3a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr
@@ -0,0 +1,20 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-67830.rs:23:5
+   |
+LL |     Wrap(|a| Some(a).into_iter())
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-67830.rs:23:5
+   |
+LL |     Wrap(|a| Some(a).into_iter())
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/impl-trait/issues/issue-67830.rs b/src/test/ui/impl-trait/issues/issue-67830.rs
new file mode 100644
index 00000000000..a308d975b43
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-67830.rs
@@ -0,0 +1,26 @@
+trait MyFn<Arg> {
+    type Output;
+    fn call(&self, arg: Arg) -> Self::Output;
+}
+
+struct Wrap<F>(F);
+
+impl<A, B, F> MyFn<A> for Wrap<F>
+where
+    F: Fn(A) -> B
+{
+    type Output = B;
+
+    fn call(&self, arg: A) -> Self::Output {
+        (self.0)(arg)
+    }
+}
+
+
+struct A;
+fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    Wrap(|a| Some(a).into_iter())
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-67830.stderr b/src/test/ui/impl-trait/issues/issue-67830.stderr
new file mode 100644
index 00000000000..74e2f99cd33
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-67830.stderr
@@ -0,0 +1,15 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-67830.rs:21:66
+   |
+LL |   fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+   |  __________________________________________________________________^
+LL | |
+LL | |     Wrap(|a| Some(a).into_iter())
+LL | | }
+   | |_^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
+
+error: aborting due to previous error
+
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-74282.rs b/src/test/ui/impl-trait/issues/issue-74282.rs
new file mode 100644
index 00000000000..654de0cd025
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-74282.rs
@@ -0,0 +1,11 @@
+#![feature(type_alias_impl_trait)]
+
+type Closure = impl Fn() -> u64;
+struct Anonymous(Closure);
+
+fn main() {
+    let y = || -> Closure { || 3 };
+    Anonymous(|| { //~ ERROR mismatched types
+        3 //~^ ERROR mismatched types
+    })
+}
diff --git a/src/test/ui/impl-trait/issues/issue-74282.stderr b/src/test/ui/impl-trait/issues/issue-74282.stderr
new file mode 100644
index 00000000000..6e02a6b2b87
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-74282.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-74282.rs:8:15
+   |
+LL |   type Closure = impl Fn() -> u64;
+   |                  ---------------- the expected opaque type
+...
+LL |       Anonymous(|| {
+   |  _______________^
+LL | |         3
+LL | |     })
+   | |_____^ expected closure, found a different closure
+   |
+   = note: expected opaque type `Closure`
+                  found closure `[closure@$DIR/issue-74282.rs:8:15: 10:6]`
+   = note: no two closures, even if identical, have the same type
+   = help: consider boxing your closure and/or using it as a trait object
+
+error[E0308]: mismatched types
+  --> $DIR/issue-74282.rs:8:5
+   |
+LL |   fn main() {
+   |             - expected `()` because of default return type
+LL |       let y = || -> Closure { || 3 };
+LL | /     Anonymous(|| {
+LL | |         3
+LL | |     })
+   | |      ^- help: consider using a semicolon here: `;`
+   | |______|
+   |        expected `()`, found struct `Anonymous`
+
+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-77987.rs b/src/test/ui/impl-trait/issues/issue-77987.rs
new file mode 100644
index 00000000000..d29710b6f54
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-77987.rs
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+trait Foo<T> {}
+impl<T, U> Foo<T> for U {}
+
+type Scope = impl Foo<()>;
+
+#[allow(unused)]
+fn infer_scope() -> Scope {
+    ()
+}
+
+#[allow(unused)]
+fn ice() -> impl Foo<Scope>
+{
+    loop {}
+}
+
+fn main() {}
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-82139.rs b/src/test/ui/impl-trait/issues/issue-82139.rs
new file mode 100644
index 00000000000..cc9167b340a
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-82139.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+trait Trait {
+    type Associated;
+    fn func() -> Self::Associated;
+}
+
+trait Bound {}
+pub struct Struct;
+
+impl Trait for Struct {
+    type Associated = impl Bound;
+
+    fn func() -> Self::Associated {
+        Some(42).map(|_| j) //~ ERROR cannot find value `j` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-82139.stderr b/src/test/ui/impl-trait/issues/issue-82139.stderr
new file mode 100644
index 00000000000..0adcd4a7a2f
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-82139.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `j` in this scope
+  --> $DIR/issue-82139.rs:15:26
+   |
+LL |         Some(42).map(|_| j)
+   |                          ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/impl-trait/issues/issue-83919.rs b/src/test/ui/impl-trait/issues/issue-83919.rs
new file mode 100644
index 00000000000..58aca77fdf1
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83919.rs
@@ -0,0 +1,31 @@
+#![feature(type_alias_impl_trait)]
+
+// edition:2021
+
+use std::future::Future;
+
+trait Foo {
+    type T;
+    type Fut2: Future<Output=Self::T>; // ICE got triggered with traits other than Future here
+    type Fut: Future<Output=Self::Fut2>;
+    fn get_fut(&self) -> Self::Fut;
+}
+
+struct Implementor;
+
+impl Foo for Implementor {
+    type T = u64;
+    type Fut2 = impl Future<Output=u64>;
+    type Fut = impl Future<Output=Self::Fut2>;
+
+    fn get_fut(&self) -> Self::Fut {
+        async move {
+            42 //~^ ERROR `{integer}` is not a future
+            // 42 does not impl Future and rustc does actually point out the error,
+            // but rustc used to panic.
+            // Putting a valid Future here always worked fine.
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-83919.stderr b/src/test/ui/impl-trait/issues/issue-83919.stderr
new file mode 100644
index 00000000000..ebd0130be8d
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-83919.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `{integer}` is not a future
+  --> $DIR/issue-83919.rs:22:9
+   |
+LL | /         async move {
+LL | |             42
+LL | |             // 42 does not impl Future and rustc does actually point out the error,
+LL | |             // but rustc used to panic.
+LL | |             // Putting a valid Future here always worked fine.
+LL | |         }
+   | |_________^ `{integer}` is not a future
+   |
+   = help: the trait `Future` is not implemented for `{integer}`
+   = note: {integer} must be a future or must implement `IntoFuture` to be awaited
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issues/issue-84073.rs b/src/test/ui/impl-trait/issues/issue-84073.rs
new file mode 100644
index 00000000000..49a34ccfa3b
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84073.rs
@@ -0,0 +1,33 @@
+use std::marker::PhantomData;
+
+pub trait StatefulFuture<S> {}
+pub struct Never<T>(PhantomData<T>);
+impl<T> StatefulFuture<T> for Never<T> {}
+
+pub struct RaceBuilder<F, S> {
+    future: F,
+    _phantom: PhantomData<S>,
+}
+
+impl<T, F> RaceBuilder<T, F>
+where
+    F: StatefulFuture<Option<T>>,
+{
+    pub fn when(self) {}
+}
+
+pub struct Race<T, R> {
+    race: R,
+    _phantom: PhantomData<T>,
+}
+
+impl<T, R> Race<T, R>
+where
+    R: Fn(RaceBuilder<T, Never<T>>),
+{
+    pub fn new(race: R) {}
+}
+
+fn main() {
+    Race::new(|race| race.when()); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/impl-trait/issues/issue-84073.stderr b/src/test/ui/impl-trait/issues/issue-84073.stderr
new file mode 100644
index 00000000000..36047d23fed
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-84073.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed for `RaceBuilder<T, Never<T>>`
+  --> $DIR/issue-84073.rs:32:16
+   |
+LL |     Race::new(|race| race.when());
+   |                ^^^^ consider giving this closure parameter the explicit type `RaceBuilder<T, Never<T>>`, where the type parameter `T` is specified
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
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-86719.rs b/src/test/ui/impl-trait/issues/issue-86719.rs
new file mode 100644
index 00000000000..f4b0b3f33fc
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86719.rs
@@ -0,0 +1,12 @@
+#![feature(type_alias_impl_trait)]
+
+trait Bar {
+    type E;
+}
+impl<S> Bar for S {
+    type E = impl ; //~ ERROR at least one trait must be specified
+    fn foo() -> Self::E { //~ ERROR `foo` is not a member
+        |_| true //~ ERROR type annotations needed
+    }
+}
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-86719.stderr b/src/test/ui/impl-trait/issues/issue-86719.stderr
new file mode 100644
index 00000000000..e2abf71c110
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86719.stderr
@@ -0,0 +1,24 @@
+error: at least one trait must be specified
+  --> $DIR/issue-86719.rs:7:14
+   |
+LL |     type E = impl ;
+   |              ^^^^
+
+error[E0407]: method `foo` is not a member of trait `Bar`
+  --> $DIR/issue-86719.rs:8:5
+   |
+LL | /     fn foo() -> Self::E {
+LL | |         |_| true
+LL | |     }
+   | |_____^ not a member of trait `Bar`
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-86719.rs:9:10
+   |
+LL |         |_| true
+   |          ^ consider giving this closure parameter a type
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0407.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/issues/issue-86800.rs b/src/test/ui/impl-trait/issues/issue-86800.rs
new file mode 100644
index 00000000000..e8cef42f208
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86800.rs
@@ -0,0 +1,48 @@
+#![feature(type_alias_impl_trait)]
+
+// edition:2021
+
+use std::future::Future;
+
+struct Connection {
+}
+
+trait Transaction {
+}
+
+struct TestTransaction<'conn> {
+    conn: &'conn Connection
+}
+
+impl<'conn> Transaction for TestTransaction<'conn> {
+}
+
+struct Context {
+}
+
+type TransactionResult<O> = Result<O, ()>;
+
+type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+//~^ ERROR unconstrained opaque type
+
+fn execute_transaction_fut<'f, F, O>(
+    f: F,
+) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<O>
+where
+    F: FnOnce(&mut dyn Transaction) -> TransactionFuture<O> + 'f
+{
+    f
+}
+
+impl Context {
+    async fn do_transaction<O>(
+        &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<O>
+    ) -> TransactionResult<O>
+    {
+        let mut conn = Connection {};
+        let mut transaction = TestTransaction { conn: &mut conn };
+        f(&mut transaction).await
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-86800.stderr b/src/test/ui/impl-trait/issues/issue-86800.stderr
new file mode 100644
index 00000000000..787aecc5b84
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-86800.stderr
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/issue-86800.rs:25:34
+   |
+LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `TransactionFuture` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-87340.rs b/src/test/ui/impl-trait/issues/issue-87340.rs
new file mode 100644
index 00000000000..f0f6d2bb61c
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-87340.rs
@@ -0,0 +1,14 @@
+#![feature(type_alias_impl_trait)]
+
+trait X {
+    type I;
+    fn f() -> Self::I;
+}
+
+impl<T> X for () {
+//~^ ERROR `T` is not constrained by the impl trait, self type, or predicates
+    type I = impl Sized;
+    fn f() -> Self::I {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-87340.stderr b/src/test/ui/impl-trait/issues/issue-87340.stderr
new file mode 100644
index 00000000000..2ab1e6a0312
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-87340.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-87340.rs:8:6
+   |
+LL | impl<T> X for () {
+   |      ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
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..af26a1f54c4
--- /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..45fadcab3f2
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
@@ -0,0 +1,23 @@
+error: implementation of `Hrtb` is not general enough
+  --> $DIR/issue-88236-2.rs:16:38
+   |
+LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:19:82
+   |
+LL |   fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |  __________________________________________________________________________________^
+LL | |     x
+LL | | }
+   | |_^ 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/issues/issue-89312.rs b/src/test/ui/impl-trait/issues/issue-89312.rs
new file mode 100644
index 00000000000..d685a6f1201
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-89312.rs
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+trait T { type Item; }
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
+
+fn filter_positive<'a>() -> Alias<'a> {
+    &S
+}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+    fun(filter_positive());
+}
+
+fn main() {
+    with_positive(|_| ());
+}
diff --git a/src/test/ui/impl-trait/issues/issue-93788.rs b/src/test/ui/impl-trait/issues/issue-93788.rs
new file mode 100644
index 00000000000..6924931cda5
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-93788.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+struct D;
+
+trait Tr {
+    type It;
+    fn foo(self) -> Option<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+    type It = ();
+    fn foo(self) -> Option<()> { None }
+}
+
+fn run<F>(f: F)
+    where for<'a> &'a D: Tr,
+          F: Fn(<&D as Tr>::It),
+{
+    let d = &D;
+    while let Some(i) = d.foo() {
+        f(i);
+    }
+}
+
+fn main() {
+    run(|_| {});
+}
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..9589b69491e 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:41: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..baa42da6446 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,12 +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
+    //~| ERROR the parameter type `T` may not live long enough
     x
 }
 
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..1272adb35e9 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
    |
@@ -112,12 +112,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
    |
@@ -132,6 +132,19 @@ LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                 |
    |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
 
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:38:72
+   |
+LL |   fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+   |  _________________________________--_____________________________________^
+   | |                                 |
+   | |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
+LL | |
+LL | |
+LL | |     x
+LL | | }
+   | |_^ ...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
    |
@@ -218,7 +231,7 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
    |                     ~~~~~~~~~~~~
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
 Some errors have detailed explanations: E0310, E0621, E0700, E0759.
 For more information about an error, try `rustc --explain E0310`.
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-return-type2-tait.rs b/src/test/ui/impl-trait/nested-return-type2-tait.rs
new file mode 100644
index 00000000000..f2217f699fb
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.rs
@@ -0,0 +1,32 @@
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+// the fact that `R` is the `::Output` projection on `F` causes
+// an intermediate inference var to be generated which is then later
+// compared against the actually found `Assoc` type.
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+type Sendable = impl Send;
+
+// The `Sendable` here is then later compared against the inference var
+// created, causing the inference var to be set to `Sendable` instead of
+// the hidden type. We already have obligations registered on the inference
+// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
+// type does not implement `Duh`, even if its hidden type does. So we error out.
+fn foo() -> impl Trait<Assoc = Sendable> {
+    //~^ ERROR `Sendable: Duh` is not satisfied
+    //~| ERROR `Sendable: Duh` is not satisfied
+    || 42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
new file mode 100644
index 00000000000..776c06b20df
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `Sendable: Duh` is not satisfied
+  --> $DIR/nested-return-type2-tait.rs:25:13
+   |
+LL | fn foo() -> impl Trait<Assoc = Sendable> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable`
+   |
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]`
+  --> $DIR/nested-return-type2-tait.rs:14:31
+   |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+   |                               ^^^^^     ^
+
+error[E0277]: the trait bound `Sendable: Duh` is not satisfied
+  --> $DIR/nested-return-type2-tait.rs:25:42
+   |
+LL |   fn foo() -> impl Trait<Assoc = Sendable> {
+   |  __________________________________________^
+LL | |
+LL | |
+LL | |     || 42
+LL | | }
+   | |_^ the trait `Duh` is not implemented for `Sendable`
+   |
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]`
+  --> $DIR/nested-return-type2-tait.rs:14:31
+   |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+   |                               ^^^^^     ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.rs b/src/test/ui/impl-trait/nested-return-type2-tait2.rs
new file mode 100644
index 00000000000..af8e0663054
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait2.rs
@@ -0,0 +1,32 @@
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+// the fact that `R` is the `::Output` projection on `F` causes
+// an intermediate inference var to be generated which is then later
+// compared against the actually found `Assoc` type.
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+type Sendable = impl Send;
+type Traitable = impl Trait<Assoc = Sendable>;
+
+// The `impl Send` here is then later compared against the inference var
+// created, causing the inference var to be set to `impl Send` instead of
+// the hidden type. We already have obligations registered on the inference
+// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
+// type does not implement `Duh`, even if its hidden type does. So we error out.
+fn foo() -> Traitable {
+    || 42
+    //~^ ERROR `Sendable: Duh` is not satisfied
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
new file mode 100644
index 00000000000..4993202e253
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Sendable: Duh` is not satisfied
+  --> $DIR/nested-return-type2-tait2.rs:27:5
+   |
+LL |     || 42
+   |     ^^^^^ the trait `Duh` is not implemented for `Sendable`
+   |
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:10]`
+  --> $DIR/nested-return-type2-tait2.rs:14:31
+   |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+   |                               ^^^^^     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.rs b/src/test/ui/impl-trait/nested-return-type2-tait3.rs
new file mode 100644
index 00000000000..74fd8a9dda0
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait3.rs
@@ -0,0 +1,31 @@
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+// the fact that `R` is the `::Output` projection on `F` causes
+// an intermediate inference var to be generated which is then later
+// compared against the actually found `Assoc` type.
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+type Traitable = impl Trait<Assoc = impl Send>;
+
+// The `impl Send` here is then later compared against the inference var
+// created, causing the inference var to be set to `impl Send` instead of
+// the hidden type. We already have obligations registered on the inference
+// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
+// type does not implement `Duh`, even if its hidden type does. So we error out.
+fn foo() -> Traitable {
+    || 42
+    //~^ ERROR `impl Send: Duh` is not satisfied
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
new file mode 100644
index 00000000000..efeaf059a3b
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `impl Send: Duh` is not satisfied
+  --> $DIR/nested-return-type2-tait3.rs:26:5
+   |
+LL |     || 42
+   |     ^^^^^ the trait `Duh` is not implemented for `impl Send`
+   |
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:10]`
+  --> $DIR/nested-return-type2-tait3.rs:14:31
+   |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+   |                               ^^^^^     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs
new file mode 100644
index 00000000000..39928d543e1
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+// the fact that `R` is the `::Output` projection on `F` causes
+// an intermediate inference var to be generated which is then later
+// compared against the actually found `Assoc` type.
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+// The `impl Send` here is then later compared against the inference var
+// created, causing the inference var to be set to `impl Send` instead of
+// the hidden type. We already have obligations registered on the inference
+// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
+// type does not implement `Duh`, even if its hidden type does.
+// Lazy TAIT would error out, but we inserted a hack to make it work again,
+// keeping backwards compatibility.
+fn foo() -> impl Trait<Assoc = impl Send> {
+    || 42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait.rs b/src/test/ui/impl-trait/nested-return-type3-tait.rs
new file mode 100644
index 00000000000..3936f4dbbb4
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<F: Duh> Trait for F {
+    type Assoc = F;
+}
+
+type Sendable = impl Send;
+
+fn foo() -> impl Trait<Assoc = Sendable> {
+    42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait2.rs b/src/test/ui/impl-trait/nested-return-type3-tait2.rs
new file mode 100644
index 00000000000..56778ed90dc
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait2.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<F: Duh> Trait for F {
+    type Assoc = F;
+}
+
+type Sendable = impl Send;
+type Traitable = impl Trait<Assoc = Sendable>;
+
+fn foo() -> Traitable {
+    42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait3.rs b/src/test/ui/impl-trait/nested-return-type3-tait3.rs
new file mode 100644
index 00000000000..04c6c92b1a3
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait3.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<F: Duh> Trait for F {
+    type Assoc = F;
+}
+
+type Traitable = impl Trait<Assoc = impl Send>;
+
+fn foo() -> Traitable {
+    42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type3.rs b/src/test/ui/impl-trait/nested-return-type3.rs
new file mode 100644
index 00000000000..74b4dae22eb
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<F: Duh> Trait for F {
+    type Assoc = F;
+}
+
+fn foo() -> impl Trait<Assoc = impl Send> {
+    42
+}
+
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
index 06a2191a017..85c6f8c462c 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 the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
 
 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 the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
 }
 
 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..26b48c7cdf7 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,34 @@ 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]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+  --> $DIR/nested_impl_trait.rs:5:46
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
+   |
+   = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+
+error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
+  --> $DIR/nested_impl_trait.rs:18:34
+   |
+LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
+   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
+   |
+   = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+
+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..5ca01a59376 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,19 @@ 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 |     }
+   |             ------------------ expected `_` because of return 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
 
 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 |     }
+   |             --------------- expected `_` because of return 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)
-   |
 
 error: aborting due to 2 previous errors
 
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..0c595f441ba 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,28 @@ 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 |     }
+   |             ---------------------- expected `_` because of return 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)
-   |
 
 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 {
+   |             ---------------------- expected `_` because of return 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);
-   |
 
 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 {
+   |             ---------------------- expected `_` because of return 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 baz() -> 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 ~         Box::new(1u32)
-   |
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9
@@ -90,100 +36,36 @@ 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 qux() -> 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[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
+   |             ---------------------- expected `_` because of return 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 bat() -> Box<dyn std::fmt::Display> {
-   |             ~~~~~~~                  +
-help: if you change the return type to expect trait objects, box the returned expressions
-   |
-LL ~         0 => return Box::new(0i32),
-LL ~         _ => Box::new(1u32),
-   |
 
 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...
+   |               ---------------------- expected `_` because of return 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 ~     })
-   |
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
    |
 LL | fn cat() -> impl std::fmt::Display {
-   |             ---------------------- expected because this return type...
-...
-LL |             return 0i32;
-   |                    ---- ...is found to be `i32` here
+   |             ---------------------- expected `_` because of return 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 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)
-   |
 
 error[E0308]: `match` arms have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14
@@ -196,16 +78,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 +90,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.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
index 65daabe419d..ade0dfa1bb3 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
@@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()`
 LL | fn test() -> impl Test {
    |              ^^^^^^^^^ 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/projection.rs b/src/test/ui/impl-trait/projection.rs
new file mode 100644
index 00000000000..b33802e2bc8
--- /dev/null
+++ b/src/test/ui/impl-trait/projection.rs
@@ -0,0 +1,29 @@
+// build-pass
+// needs to be build-pass, because it is a regression test for a mir validation failure
+// that only happens during codegen.
+
+struct D;
+
+trait Tr {
+    type It;
+    fn foo(self) -> Option<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+    type It = ();
+    fn foo(self) -> Option<()> { None }
+}
+
+fn run<F>(f: F)
+    where for<'a> &'a D: Tr,
+          F: Fn(<&D as Tr>::It),
+{
+    let d = &D;
+    while let Some(i) = d.foo() {
+        f(i);
+    }
+}
+
+fn main() {
+    run(|_| {});
+}
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..7bd5cff31bb
--- /dev/null
+++ b/src/test/ui/impl-trait/question_mark.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::fmt::Debug;
+
+#[derive(Debug)]
+pub struct Target;
+
+#[derive(Debug)]
+pub struct Source;
+impl From<Source> for Target {
+    fn from(_: Source) -> Self {
+        Self
+    }
+}
+
+fn maybe_source() -> Result<(), Source> {
+    todo!()
+}
+
+pub fn typaram() -> Result<(), impl Debug> {
+    maybe_source()?;
+    Ok::<_, Target>(())
+}
+
+pub fn direct() -> Result<(), impl Debug> {
+    maybe_source()?;
+    Err(Target)
+}
+
+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-2.rs b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
new file mode 100644
index 00000000000..6b200d7e3a8
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+
+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 //~ ERROR can't compare `Bar` with `(Bar, i32)`
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
new file mode 100644
index 00000000000..5476bf9d277
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
@@ -0,0 +1,11 @@
+error[E0277]: can't compare `Bar` with `(Bar, i32)`
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:14:5
+   |
+LL |     Bar
+   |     ^^^ no implementation for `Bar == (Bar, i32)`
+   |
+   = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
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..6aa832cde71
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -0,0 +1,30 @@
+#![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 {
+            //~^ ERROR impl has stricter requirements than trait
+            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..19d5cdb9d0a
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -0,0 +1,25 @@
+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[E0276]: impl has stricter requirements than trait
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:23:9
+   |
+LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `b::Bar: PartialEq<(b::Bar, i32)>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0276`.
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..ad0a003e879
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+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/trait_resolution.rs b/src/test/ui/impl-trait/trait_resolution.rs
new file mode 100644
index 00000000000..8dcbbfd6e64
--- /dev/null
+++ b/src/test/ui/impl-trait/trait_resolution.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+use std::fmt::Debug;
+
+pub struct EventStream<S> {
+    stream: S,
+}
+
+impl<S: Debug> EventStream<S> {
+    fn into_stream(self) -> impl Debug {
+        unimplemented!()
+    }
+
+    pub fn into_reader(self) -> impl Debug {
+        ReaderStream::from(self.into_stream())
+    }
+}
+
+#[derive(Debug)]
+pub struct ReaderStream<S> {
+    stream: S,
+}
+
+impl<S> From<S> for ReaderStream<S> {
+    fn from(stream: S) -> Self {
+        ReaderStream { stream }
+    }
+}
+
+fn main() {}
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..05b09668016
--- /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; //~ ERROR unconstrained opaque type
+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..4d8f96de162
--- /dev/null
+++ b/src/test/ui/impl-trait/two_tait_defining_each_other2.stderr
@@ -0,0 +1,27 @@
+error: unconstrained opaque type
+  --> $DIR/two_tait_defining_each_other2.rs:3:10
+   |
+LL | type A = impl Foo;
+   |          ^^^^^^^^
+   |
+   = note: `A` must be used in combination with a concrete type within the same module
+
+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 2 previous errors
+
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..b1175a5952e 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:10: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..bb9cab742a5 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.rs
+++ b/src/test/ui/impl-trait/type_parameters_captured.rs
@@ -6,6 +6,7 @@ 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
+    //~| ERROR the parameter type `T` may not live long enough
     x
 }
 
diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr
index 40e50b9922f..c4ca34a6ed3 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -6,6 +6,19 @@ LL | fn foo<T>(x: T) -> impl Any + 'static {
    |        |
    |        help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error: aborting due to previous error
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/type_parameters_captured.rs:7:39
+   |
+LL |   fn foo<T>(x: T) -> impl Any + 'static {
+   |  ________-______________________________^
+   | |        |
+   | |        help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | |
+LL | |
+LL | |     x
+LL | | }
+   | |_^ ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
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`.
diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs
index fecba721ac9..fde59f39b1c 100644
--- a/src/test/ui/issues-71798.rs
+++ b/src/test/ui/issues-71798.rs
@@ -1,5 +1,7 @@
 fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
-    *x //~^ ERROR `u32` is not a future
+    //~^ ERROR `u32` is not a future
+    //~| ERROR `u32` is not a future
+    *x
 }
 
 fn main() {
diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr
index bc4dc9ebf9e..63669c0513d 100644
--- a/src/test/ui/issues-71798.stderr
+++ b/src/test/ui/issues-71798.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `u` in this scope
-  --> $DIR/issues-71798.rs:6:24
+  --> $DIR/issues-71798.rs:8:24
    |
 LL |     let _ = test_ref & u;
    |                        ^ not found in this scope
@@ -13,7 +13,21 @@ LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
    = help: the trait `Future` is not implemented for `u32`
    = note: u32 must be a future or must implement `IntoFuture` to be awaited
 
-error: aborting due to 2 previous errors
+error[E0277]: `u32` is not a future
+  --> $DIR/issues-71798.rs:1:69
+   |
+LL |   fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+   |  _____________________________________________________________________^
+LL | |
+LL | |
+LL | |     *x
+LL | | }
+   | |_^ `u32` is not a future
+   |
+   = help: the trait `Future` is not implemented for `u32`
+   = note: u32 must be a future or must implement `IntoFuture` to be awaited
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.rs b/src/test/ui/lazy-type-alias-impl-trait/branches.rs
new file mode 100644
index 00000000000..aa172f3f19b
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches.rs
@@ -0,0 +1,14 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        vec![42_i32]
+    } else {
+        std::iter::empty().collect()
+        //~^ ERROR `Foo` cannot be built from an iterator over elements of type `_`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
new file mode 100644
index 00000000000..c3902f34706
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
@@ -0,0 +1,16 @@
+error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
+  --> $DIR/branches.rs:9:28
+   |
+LL |         std::iter::empty().collect()
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |
+   = help: the trait `FromIterator<_>` is not implemented for `Foo`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches2.rs b/src/test/ui/lazy-type-alias-impl-trait/branches2.rs
new file mode 100644
index 00000000000..af605e4d806
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches2.rs
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+
+// run-pass
+
+type Foo = impl std::iter::FromIterator<i32> + PartialEq<Vec<i32>> + std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        vec![42_i32]
+    } else {
+        std::iter::empty().collect()
+    }
+}
+
+fn bar(b: bool) -> impl PartialEq<Vec<i32>> + std::fmt::Debug {
+    if b {
+        vec![42_i32]
+    } else {
+        std::iter::empty().collect()
+    }
+}
+
+fn main() {
+    assert_eq!(foo(true), vec![42]);
+    assert_eq!(foo(false), vec![]);
+    assert_eq!(bar(true), vec![42]);
+    assert_eq!(bar(false), vec![]);
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
new file mode 100644
index 00000000000..10f6bd74031
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
@@ -0,0 +1,46 @@
+// check-pass
+
+#![feature(gen_future, generator_trait, negative_impls)]
+
+use std::ops::{Generator, GeneratorState};
+use std::task::{Poll, Context};
+use std::future::{Future};
+use std::ptr::NonNull;
+use std::pin::Pin;
+
+fn main() {}
+
+#[derive(Debug, Copy, Clone)]
+pub struct ResumeTy(NonNull<Context<'static>>);
+
+unsafe impl Send for ResumeTy {}
+
+unsafe impl Sync for ResumeTy {}
+
+pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+where
+    T: Generator<ResumeTy, Yield = ()>,
+{
+    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
+
+    // We rely on the fact that async/await futures are immovable in order to create
+    // self-referential borrows in the underlying generator.
+    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
+
+    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
+        type Output = T::Return;
+        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+            // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
+            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
+
+            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
+            // `.await` lowering will safely cast that back to a `&mut Context`.
+            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
+                GeneratorState::Yielded(()) => Poll::Pending,
+                GeneratorState::Complete(x) => Poll::Ready(x),
+            }
+        }
+    }
+
+    GenFuture(gen)
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs
new file mode 100644
index 00000000000..d07d732c785
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/infer_cross_function.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+fn main() {}
+
+trait Reader {}
+
+struct Unit<R>(R);
+struct ResDwarf<R>(R);
+
+struct Context<R: Reader> {
+    dwarf: ResDwarf<R>,
+}
+
+struct Range;
+
+struct ResUnit<R>(R);
+
+impl<R: Reader + 'static> Context<R> {
+    fn find_dwarf_unit(&self, probe: u64) -> Option<&Unit<R>> {
+        let x = self.find_units(probe);
+        None
+    }
+
+    fn find_units(&self, probe: u64) -> impl Iterator<Item = &ResUnit<R>> {
+        std::iter::empty()
+    }
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs
new file mode 100644
index 00000000000..f75a88aa8f0
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/lifetime_inference.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn main() {}
+
+fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
+    move || iter.nth(step)
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/nested.rs b/src/test/ui/lazy-type-alias-impl-trait/nested.rs
new file mode 100644
index 00000000000..f8291112739
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/nested.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+fn main() {}
+
+struct RawTableInner<A> {
+    alloc: A,
+}
+
+impl<A> RawTableInner<A> {
+    fn prepare_resize(
+        self,
+    ) -> ScopeGuard<Self, impl FnMut(&mut Self)> {
+        ScopeGuard { dropfn: move |self_| {}, value: self,  }
+    }
+}
+
+pub struct ScopeGuard<T, F>
+where
+    F: FnMut(&mut T),
+{
+    dropfn: F,
+    value: T,
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs
new file mode 100644
index 00000000000..8d03b5158d6
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+fn main() {}
+
+fn filter_fold<T, Acc, PRED: FnMut(&T) -> bool, FOLD: FnMut(Acc, T) -> Acc>(
+    mut predicate: PRED,
+    mut fold: FOLD,
+) -> impl FnMut(Acc, T) -> Acc {
+    move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
+}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion.rs
new file mode 100644
index 00000000000..cf7cd5d26ca
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion.rs
@@ -0,0 +1,23 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+type Foo = impl std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        return 42
+    }
+    let x: u32 = foo(false);
+    99
+}
+
+fn bar(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return 42
+    }
+    let x: u32 = bar(false);
+    99
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs
new file mode 100644
index 00000000000..1cc64ea17e7
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion2.rs
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        return vec![];
+    }
+    let x: Vec<i32> = foo(false);
+    std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator
+}
+
+fn bar(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return vec![]
+    }
+    let x: Vec<i32> = bar(false);
+    std::iter::empty().collect()
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr
new file mode 100644
index 00000000000..1f6201a8300
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion2.stderr
@@ -0,0 +1,16 @@
+error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
+  --> $DIR/recursion2.rs:10:24
+   |
+LL |     std::iter::empty().collect()
+   |                        ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |
+   = help: the trait `FromIterator<_>` is not implemented for `Foo`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs
new file mode 100644
index 00000000000..7f1cedae068
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion3.rs
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        return 42
+    }
+    let x: u32 = foo(false) + 42; //~ ERROR cannot add
+    99
+}
+
+fn bar(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return 42
+    }
+    let x: u32 = bar(false) + 42; //~ ERROR cannot add
+    99
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr
new file mode 100644
index 00000000000..e1d5cafedc8
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion3.stderr
@@ -0,0 +1,19 @@
+error[E0369]: cannot add `{integer}` to `Foo`
+  --> $DIR/recursion3.rs:9:29
+   |
+LL |     let x: u32 = foo(false) + 42;
+   |                  ---------- ^ -- {integer}
+   |                  |
+   |                  Foo
+
+error[E0369]: cannot add `{integer}` to `impl Debug`
+  --> $DIR/recursion3.rs:17:29
+   |
+LL |     let x: u32 = bar(false) + 42;
+   |                  ---------- ^ -- {integer}
+   |                  |
+   |                  impl Debug
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs b/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs
new file mode 100644
index 00000000000..57dd7fb067c
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.rs
@@ -0,0 +1,23 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        return vec![];
+    }
+    let mut x = foo(false);
+    x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator
+    vec![]
+}
+
+fn bar(b: bool) -> impl std::fmt::Debug {
+    if b {
+        return vec![];
+    }
+    let mut x = bar(false);
+    x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator
+    vec![]
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
new file mode 100644
index 00000000000..42a1f782d29
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
@@ -0,0 +1,29 @@
+error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
+  --> $DIR/recursion4.rs:10:28
+   |
+LL |     x = std::iter::empty().collect();
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |
+   = help: the trait `FromIterator<_>` is not implemented for `Foo`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
+  --> $DIR/recursion4.rs:19:28
+   |
+LL |     x = std::iter::empty().collect();
+   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |
+   = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs
new file mode 100644
index 00000000000..00710149823
--- /dev/null
+++ b/src/test/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+fn main() {}
+
+pub struct PairSlices<'a, 'b, T> {
+    pub(crate) a0: &'a mut [T],
+    pub(crate) a1: &'a mut [T],
+    pub(crate) b0: &'b [T],
+    pub(crate) b1: &'b [T],
+}
+
+impl<'a, 'b, T> PairSlices<'a, 'b, T> {
+    pub fn remainder(self) -> impl Iterator<Item = &'b [T]> {
+        IntoIterator::into_iter([self.b0, self.b1])
+    }
+}
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
index ea0d0ccbc55..133679f30f8 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
@@ -6,7 +6,8 @@ trait Future {
 use std::error::Error;
 
 fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
-//~^ ERROR not satisfied
+    //~^ ERROR not satisfied
+    //~| ERROR not satisfied
     Ok(())
 }
 
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
index ef1127c59ac..a3badd7b25a 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -4,6 +4,17 @@ error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>`
 
-error: aborting due to previous error
+error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied
+  --> $DIR/lifetime-elision-return-type-trait.rs:8:56
+   |
+LL |   fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
+   |  ________________________________________________________^
+LL | |
+LL | |
+LL | |     Ok(())
+LL | | }
+   | |_^ the trait `Future` is not implemented for `Result<(), _>`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.rs b/src/test/ui/lint/inline-trait-and-foreign-items.rs
index 6321b3c76e4..13dab7ed954 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.rs
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.rs
@@ -23,7 +23,7 @@ impl Trait for () {
     type T = Self;
 
     #[inline] //~ ERROR attribute should be applied to function or closure
-    type U = impl Trait; //~ ERROR could not find defining uses
+    type U = impl Trait; //~ ERROR unconstrained opaque type
 }
 
 extern "C" {
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
index 6ac884c12ce..fc7e89e4f4c 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
@@ -61,11 +61,13 @@ LL |     #[inline]
 LL |     type T;
    |     ------- not a function or closure
 
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
 LL |     type U = impl Trait;
    |              ^^^^^^^^^^
+   |
+   = note: `U` must be used in combination with a concrete type within the same module
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
diff --git a/src/test/ui/lint/lint-ctypes-73249-2.rs b/src/test/ui/lint/lint-ctypes-73249-2.rs
index fe578f51b63..691047c8a40 100644
--- a/src/test/ui/lint/lint-ctypes-73249-2.rs
+++ b/src/test/ui/lint/lint-ctypes-73249-2.rs
@@ -23,7 +23,7 @@ pub struct A<T: Foo> {
 }
 
 extern "C" {
-    pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73249-2.stderr b/src/test/ui/lint/lint-ctypes-73249-2.stderr
index 36dbe3217d7..7c85e9fa85c 100644
--- a/src/test/ui/lint/lint-ctypes-73249-2.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-2.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-2.rs:26:25
    |
 LL |     pub fn lint_me() -> A<()>;
diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs
index ec12de00739..ef8ab7e03d2 100644
--- a/src/test/ui/lint/lint-ctypes-73249-3.rs
+++ b/src/test/ui/lint/lint-ctypes-73249-3.rs
@@ -17,7 +17,7 @@ pub struct A {
 }
 
 extern "C" {
-    pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73249-3.stderr b/src/test/ui/lint/lint-ctypes-73249-3.stderr
index e987ec90228..83e2a233c43 100644
--- a/src/test/ui/lint/lint-ctypes-73249-3.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-3.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-3.rs:20:25
    |
 LL |     pub fn lint_me() -> A;
diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs
index 58c2d7a501a..083fb6c5fb1 100644
--- a/src/test/ui/lint/lint-ctypes-73249-5.rs
+++ b/src/test/ui/lint/lint-ctypes-73249-5.rs
@@ -17,7 +17,7 @@ pub struct A {
 }
 
 extern "C" {
-    pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73249-5.stderr b/src/test/ui/lint/lint-ctypes-73249-5.stderr
index 749714c7df8..37781d78cf2 100644
--- a/src/test/ui/lint/lint-ctypes-73249-5.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-5.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73249-5.rs:20:25
    |
 LL |     pub fn lint_me() -> A;
diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs
index dc4c7efd7ef..145ba784f7c 100644
--- a/src/test/ui/lint/lint-ctypes-73251-1.rs
+++ b/src/test/ui/lint/lint-ctypes-73251-1.rs
@@ -20,7 +20,7 @@ fn assign() -> Qux {
 }
 
 extern "C" {
-    pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `impl Baz`
+    pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr
index 505ccd5a930..76b19d37e21 100644
--- a/src/test/ui/lint/lint-ctypes-73251-1.stderr
+++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Baz`, which is not FFI-safe
+error: `extern` block uses type `Qux`, which is not FFI-safe
   --> $DIR/lint-ctypes-73251-1.rs:23:25
    |
 LL |     pub fn lint_me() -> <u32 as Foo>::Assoc;
diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs
index 717ca4986f7..df71a945796 100644
--- a/src/test/ui/lint/lint-ctypes-73251-2.rs
+++ b/src/test/ui/lint/lint-ctypes-73251-2.rs
@@ -33,7 +33,7 @@ fn use_of_b() -> AliasB {
 }
 
 extern "C" {
-    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA<Assoc = u32>`
+    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `AliasA`
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr
index d7e10db441e..64f0fb2d892 100644
--- a/src/test/ui/lint/lint-ctypes-73251-2.stderr
+++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl TraitA<Assoc = u32>`, which is not FFI-safe
+error: `extern` block uses type `AliasA`, which is not FFI-safe
   --> $DIR/lint-ctypes-73251-2.rs:36:25
    |
 LL |     pub fn lint_me() -> <AliasB as TraitB>::Assoc;
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
index 3a62b6a21a5..b7cc38e99fc 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -9,7 +9,7 @@ pub fn ret_closure() -> A {
 
 extern "C" {
     pub fn a(_: A);
-    //~^ ERROR `extern` block uses type `impl Fn()`, which is not FFI-safe [improper_ctypes]
+    //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes]
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
index 5afbef778b3..62d00fd6835 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -1,4 +1,4 @@
-error: `extern` block uses type `impl Fn()`, which is not FFI-safe
+error: `extern` block uses type `A`, which is not FFI-safe
   --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
    |
 LL |     pub fn a(_: A);
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.rs b/src/test/ui/never_type/feature-gate-never_type_fallback.rs
index 3b896ec9d70..7d020841180 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.rs
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.rs
@@ -6,7 +6,8 @@ fn main() {}
 
 trait T {}
 
-fn should_ret_unit() -> impl T {
-    //~^ ERROR the trait bound `(): T` is not satisfied
-    panic!()
+fn should_ret_unit() {
+    foo(panic!()) //~ ERROR
 }
+
+fn foo(_: impl T) {}
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 670f76867ce..54abed38300 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -1,8 +1,14 @@
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/feature-gate-never_type_fallback.rs:9:25
+  --> $DIR/feature-gate-never_type_fallback.rs:10:5
    |
-LL | fn should_ret_unit() -> impl T {
-   |                         ^^^^^^ the trait `T` is not implemented for `()`
+LL |     foo(panic!())
+   |     ^^^ the trait `T` is not implemented for `()`
+   |
+note: required by a bound in `foo`
+  --> $DIR/feature-gate-never_type_fallback.rs:13:16
+   |
+LL | fn foo(_: impl T) {}
+   |                ^ required by this bound in `foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/never_type/impl_trait_fallback.rs b/src/test/ui/never_type/impl_trait_fallback.rs
new file mode 100644
index 00000000000..cc9520c1b24
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+fn main() {}
+
+trait T {}
+impl T for () {}
+
+fn should_ret_unit() -> impl T {
+    panic!()
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback2.rs b/src/test/ui/never_type/impl_trait_fallback2.rs
new file mode 100644
index 00000000000..f73d953bdbd
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback2.rs
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait T {}
+impl T for i32 {}
+
+fn should_ret_unit() -> impl T {
+    //~^ ERROR `(): T` is not satisfied
+    panic!()
+}
+
+type Foo = impl T;
+
+fn a() -> Foo {
+    panic!()
+}
+
+fn b() -> Foo {
+    42
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback2.stderr b/src/test/ui/never_type/impl_trait_fallback2.stderr
new file mode 100644
index 00000000000..2f50b9d2459
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback2.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): T` is not satisfied
+  --> $DIR/impl_trait_fallback2.rs:8:25
+   |
+LL | fn should_ret_unit() -> impl T {
+   |                         ^^^^^^ the trait `T` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/never_type/impl_trait_fallback3.rs b/src/test/ui/never_type/impl_trait_fallback3.rs
new file mode 100644
index 00000000000..26ce9b93105
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback3.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait T {
+    type Assoc;
+}
+
+type Foo = impl T;
+//~^ ERROR unconstrained opaque type
+
+fn a() -> Foo {
+    // This is not a defining use, it doesn't actually constrain the opaque type.
+    panic!()
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback3.stderr b/src/test/ui/never_type/impl_trait_fallback3.stderr
new file mode 100644
index 00000000000..121019d5f69
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback3.stderr
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/impl_trait_fallback3.rs:9:12
+   |
+LL | type Foo = impl T;
+   |            ^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/never_type/impl_trait_fallback4.rs b/src/test/ui/never_type/impl_trait_fallback4.rs
new file mode 100644
index 00000000000..fe62773fa02
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback4.rs
@@ -0,0 +1,24 @@
+#![feature(type_alias_impl_trait)]
+
+trait T {
+    type Assoc: Cake;
+}
+
+trait Cake: std::fmt::Display {
+    fn cake() -> Self;
+}
+
+type Foo = impl T;
+
+fn foo() -> impl T {
+    //~^ ERROR `(): T` is not satisfied
+    panic!()
+}
+
+fn a() -> Foo {
+    foo()
+}
+
+fn main() {
+    println!("{}", <Foo as T>::Assoc::cake());
+}
diff --git a/src/test/ui/never_type/impl_trait_fallback4.stderr b/src/test/ui/never_type/impl_trait_fallback4.stderr
new file mode 100644
index 00000000000..f2e216e9044
--- /dev/null
+++ b/src/test/ui/never_type/impl_trait_fallback4.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): T` is not satisfied
+  --> $DIR/impl_trait_fallback4.rs:13:13
+   |
+LL | fn foo() -> impl T {
+   |             ^^^^^^ the trait `T` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
index 0d7ee037692..2f4cbf8322b 100644
--- a/src/test/ui/nll/issue-52113.rs
+++ b/src/test/ui/nll/issue-52113.rs
@@ -29,9 +29,9 @@ fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazi
 fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
     let x = move || {
         let value: &'a u32 = value;
-        data.push(value);
+        data.push(value); //~ ERROR lifetime may not live long enough
     };
-    x //~ ERROR lifetime may not live long enough
+    x
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
index f70ae2edd7f..42ff1866893 100644
--- a/src/test/ui/nll/issue-52113.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -1,13 +1,13 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-52113.rs:34:5
+  --> $DIR/issue-52113.rs:32:9
    |
 LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
    |                --  -- lifetime `'b` defined here
    |                |
    |                lifetime `'a` defined here
 ...
-LL |     x
-   |     ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+LL |         data.push(value);
+   |         ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
 
diff --git a/src/test/ui/nll/issue-73159-rpit-static.rs b/src/test/ui/nll/issue-73159-rpit-static.rs
index e29ba09b369..97dc016068b 100644
--- a/src/test/ui/nll/issue-73159-rpit-static.rs
+++ b/src/test/ui/nll/issue-73159-rpit-static.rs
@@ -7,8 +7,8 @@ struct Foo<'a>(&'a [u8]);
 
 impl<'a> Foo<'a> {
     fn make_it(&self) -> impl Iterator<Item = u8> {
-        //~^ ERROR: captures lifetime that does not appear in bounds
         self.0.iter().copied()
+        //~^ ERROR: captures lifetime that does not appear in bounds
     }
 }
 
diff --git a/src/test/ui/nll/issue-73159-rpit-static.stderr b/src/test/ui/nll/issue-73159-rpit-static.stderr
index 6c7cd0c8254..a3e9c0b44c2 100644
--- a/src/test/ui/nll/issue-73159-rpit-static.stderr
+++ b/src/test/ui/nll/issue-73159-rpit-static.stderr
@@ -1,10 +1,11 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/issue-73159-rpit-static.rs:9:26
+  --> $DIR/issue-73159-rpit-static.rs:10:9
    |
 LL | impl<'a> Foo<'a> {
    |      -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
 LL |     fn make_it(&self) -> impl Iterator<Item = u8> {
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         self.0.iter().copied()
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/relate_tys/opaque-hrtb.rs b/src/test/ui/nll/relate_tys/opaque-hrtb.rs
new file mode 100644
index 00000000000..0fbe6a63c0b
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/opaque-hrtb.rs
@@ -0,0 +1,16 @@
+#![feature(nll)]
+
+trait MyTrait<T> {}
+
+struct Foo;
+impl<T> MyTrait<T> for Foo {}
+
+fn bar<Input>() -> impl MyTrait<Input> {
+    Foo
+}
+
+fn foo() -> impl for<'a> MyTrait<&'a str> {
+    bar() //~ ERROR implementation of `MyTrait` is not general enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/relate_tys/opaque-hrtb.stderr b/src/test/ui/nll/relate_tys/opaque-hrtb.stderr
new file mode 100644
index 00000000000..4c8b66f21ab
--- /dev/null
+++ b/src/test/ui/nll/relate_tys/opaque-hrtb.stderr
@@ -0,0 +1,11 @@
+error: implementation of `MyTrait` is not general enough
+  --> $DIR/opaque-hrtb.rs:13:5
+   |
+LL |     bar()
+   |     ^^^^^ implementation of `MyTrait` is not general enough
+   |
+   = note: `impl MyTrait<&'2 str>` must implement `MyTrait<&'1 str>`, for any lifetime `'1`...
+   = note: ...but it actually implements `MyTrait<&'2 str>`, for some specific lifetime `'2`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs
index 8af23aad726..c04185d0814 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs
@@ -8,8 +8,8 @@ trait Foo<'a> {
 impl<'a, T> Foo<'a> for T { }
 
 fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-//~^ ERROR captures lifetime that does not appear in bounds
     x
+    //~^ ERROR captures lifetime that does not appear in bounds
 }
 
 fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
index 3e6fe789a8b..42d9f057aaa 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -1,10 +1,10 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/impl-trait-captures.rs:10:25
+  --> $DIR/impl-trait-captures.rs:11:5
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-   |                  --     ^^^^^^^^^^^^
-   |                  |
-   |                  hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
+   |                  -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
+LL |     x
+   |     ^
    |
 help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound
    |
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
index 0c7d8acb052..3548ad03a7d 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs
@@ -5,11 +5,11 @@
 use std::fmt::Debug;
 
 fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: Debug,
 {
     x
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a
@@ -20,11 +20,11 @@ where
 }
 
 fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 where
     T: 'b + Debug,
 {
     x
+    //~^ ERROR the parameter type `T` may not live long enough [E0309]
 }
 
 fn outlives_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
index 053aef951f2..31ee540cce9 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr
@@ -1,16 +1,16 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:7:35
+  --> $DIR/impl-trait-outlives.rs:11:5
    |
-LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
-   |                                   ^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/impl-trait-outlives.rs:22:42
+  --> $DIR/impl-trait-outlives.rs:26:5
    |
-LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
-   |                                          ^^^^^^^^^^^^^^^
+LL |     x
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs
index 91a63bafd99..c2954868f78 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.rs
+++ b/src/test/ui/parser/fn-header-semantic-fail.rs
@@ -9,8 +9,9 @@ fn main() {
     unsafe fn ff2() {} // OK.
     const fn ff3() {} // OK.
     extern "C" fn ff4() {} // OK.
-    const async unsafe extern "C" fn ff5() {} // OK.
+    const async unsafe extern "C" fn ff5() {}
     //~^ ERROR functions cannot be both `const` and `async`
+    //~| ERROR cycle detected
 
     trait X {
         async fn ft1(); //~ ERROR functions in traits cannot be declared `async`
@@ -26,15 +27,16 @@ fn main() {
     struct Y;
     impl X for Y {
         async fn ft1() {} //~ ERROR functions in traits cannot be declared `async`
-        //~^ ERROR method `ft1` has an incompatible type for trait
+        //~^ ERROR impl has stricter requirements than trait
         unsafe fn ft2() {} // OK.
         const fn ft3() {} //~ ERROR functions in traits cannot be declared const
         extern "C" fn ft4() {}
         const async unsafe extern "C" fn ft5() {}
         //~^ ERROR functions in traits cannot be declared `async`
         //~| ERROR functions in traits cannot be declared const
-        //~| ERROR method `ft5` has an incompatible type for trait
         //~| ERROR functions cannot be both `const` and `async`
+        //~| ERROR cycle detected
+        //~| ERROR impl has stricter requirements than trait
     }
 
     impl Y {
@@ -44,6 +46,7 @@ fn main() {
         extern "C" fn fi4() {} // OK.
         const async unsafe extern "C" fn fi5() {}
         //~^ ERROR functions cannot be both `const` and `async`
+        //~| ERROR cycle detected
     }
 
     extern "C" {
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 8eaba559a62..bd3b9181123 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -1,14 +1,14 @@
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:12:5
    |
-LL |     const async unsafe extern "C" fn ff5() {} // OK.
+LL |     const async unsafe extern "C" fn ff5() {}
    |     ^^^^^-^^^^^------------------------------
    |     |     |
    |     |     `async` because of this
    |     `const` because of this
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:16:9
+  --> $DIR/fn-header-semantic-fail.rs:17:9
    |
 LL |         async fn ft1();
    |         -----^^^^^^^^^^
@@ -19,19 +19,19 @@ LL |         async fn ft1();
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:18:9
+  --> $DIR/fn-header-semantic-fail.rs:19:9
    |
 LL |         const fn ft3();
    |         ^^^^^ functions in traits cannot be const
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^ functions in traits cannot be const
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |         const async unsafe extern "C" fn ft5();
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:20:9
+  --> $DIR/fn-header-semantic-fail.rs:21:9
    |
 LL |         const async unsafe extern "C" fn ft5();
    |         ^^^^^-^^^^^----------------------------
@@ -51,7 +51,7 @@ LL |         const async unsafe extern "C" fn ft5();
    |         `const` because of this
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:28:9
+  --> $DIR/fn-header-semantic-fail.rs:29:9
    |
 LL |         async fn ft1() {}
    |         -----^^^^^^^^^^^^
@@ -62,19 +62,19 @@ LL |         async fn ft1() {}
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:31:9
+  --> $DIR/fn-header-semantic-fail.rs:32:9
    |
 LL |         const fn ft3() {}
    |         ^^^^^ functions in traits cannot be const
 
 error[E0379]: functions in traits cannot be declared const
-  --> $DIR/fn-header-semantic-fail.rs:33:9
+  --> $DIR/fn-header-semantic-fail.rs:34:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^ functions in traits cannot be const
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/fn-header-semantic-fail.rs:33:9
+  --> $DIR/fn-header-semantic-fail.rs:34:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -85,7 +85,7 @@ LL |         const async unsafe extern "C" fn ft5() {}
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:33:9
+  --> $DIR/fn-header-semantic-fail.rs:34:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^-^^^^^------------------------------
@@ -94,7 +94,7 @@ LL |         const async unsafe extern "C" fn ft5() {}
    |         `const` because of this
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:45:9
+  --> $DIR/fn-header-semantic-fail.rs:47:9
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^-^^^^^------------------------------
@@ -103,7 +103,7 @@ LL |         const async unsafe extern "C" fn fi5() {}
    |         `const` because of this
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:50:18
+  --> $DIR/fn-header-semantic-fail.rs:53:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -116,7 +116,7 @@ LL |         fn fe1();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:51:19
+  --> $DIR/fn-header-semantic-fail.rs:54:19
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -130,7 +130,7 @@ LL |         fn fe2();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:52:18
+  --> $DIR/fn-header-semantic-fail.rs:55:18
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -144,7 +144,7 @@ LL |         fn fe3();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:53:23
+  --> $DIR/fn-header-semantic-fail.rs:56:23
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -158,7 +158,7 @@ LL |         fn fe4();
    |         ~~
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:54:42
+  --> $DIR/fn-header-semantic-fail.rs:57:42
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
@@ -172,7 +172,7 @@ LL |         fn fe5();
    |         ~~
 
 error: functions cannot be both `const` and `async`
-  --> $DIR/fn-header-semantic-fail.rs:54:9
+  --> $DIR/fn-header-semantic-fail.rs:57:9
    |
 LL |         const async unsafe extern "C" fn fe5();
    |         ^^^^^-^^^^^----------------------------
@@ -180,43 +180,133 @@ LL |         const async unsafe extern "C" fn fe5();
    |         |     `async` because of this
    |         `const` because of this
 
-error[E0053]: method `ft1` has an incompatible type for trait
-  --> $DIR/fn-header-semantic-fail.rs:28:24
+error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:12:44
    |
-LL |         async fn ft1() {}
-   |                        ^
-   |                        |
-   |                        checked the `Output` of this `async fn`, found opaque type
-   |                        expected `()`, found opaque type
+LL |     const async unsafe extern "C" fn ff5() {}
+   |                                            ^
+   |
+note: ...which requires borrow-checking `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
+   |
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
+   |
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::ff5`...
+  --> $DIR/fn-header-semantic-fail.rs:12:5
    |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/fn-header-semantic-fail.rs:16:23
+LL |     const async unsafe extern "C" fn ff5() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/fn-header-semantic-fail.rs:29:9
    |
 LL |         async fn ft1();
-   |                       ^
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn() -> impl Future<Output = ()>`
+   |         --------------- definition of `ft1` from trait
+...
+LL |         async fn ft1() {}
+   |         ^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/fn-header-semantic-fail.rs:34:9
+   |
+LL |         const async unsafe extern "C" fn ft5();
+   |         --------------------------------------- definition of `ft5` from trait
+...
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
 
-error[E0053]: method `ft5` has an incompatible type for trait
-  --> $DIR/fn-header-semantic-fail.rs:33:48
+error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:34:48
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |                                                ^
-   |                                                |
-   |                                                checked the `Output` of this `async fn`, found opaque type
-   |                                                expected `()`, found opaque type
    |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/fn-header-semantic-fail.rs:20:47
+note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:34:9
    |
-LL |         const async unsafe extern "C" fn ft5();
-   |                                               ^
-   = note: expected fn pointer `unsafe extern "C" fn()`
-              found fn pointer `unsafe extern "C" fn() -> impl Future<Output = ()>`
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:34:9
+   |
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5`...
+  --> $DIR/fn-header-semantic-fail.rs:34:9
+   |
+LL |         const async unsafe extern "C" fn ft5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 40:6>::ft5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0391]: cycle detected when computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5::{opaque#0}`
+  --> $DIR/fn-header-semantic-fail.rs:47:48
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |                                                ^
+   |
+note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:47:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:47:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5`...
+  --> $DIR/fn-header-semantic-fail.rs:47:9
+   |
+LL |         const async unsafe extern "C" fn fi5() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
+   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:42:5: 50:6>::fi5::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/fn-header-semantic-fail.rs:5:1
+   |
+LL | / #![feature(const_extern_fn)]
+LL | |
+LL | | fn main() {
+LL | |     async fn ff1() {} // OK.
+...  |
+LL | |     }
+LL | | }
+   | |_^
 
-error: aborting due to 20 previous errors
+error: aborting due to 23 previous errors
 
-Some errors have detailed explanations: E0053, E0379, E0706.
-For more information about an error, try `rustc --explain E0053`.
+Some errors have detailed explanations: E0276, E0379, E0391, E0706.
+For more information about an error, try `rustc --explain E0276`.
diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs
index f295cf15d08..68ea4a026d7 100644
--- a/src/test/ui/polymorphization/generators.rs
+++ b/src/test/ui/polymorphization/generators.rs
@@ -32,7 +32,6 @@ where
 
 #[rustc_polymorphize_error]
 pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-    //~^ ERROR item has unused generic parameters
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
@@ -58,7 +57,6 @@ pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Retu
 
 #[rustc_polymorphize_error]
 pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-    //~^ ERROR item has unused generic parameters
     || {
         //~^ ERROR item has unused generic parameters
         yield 1;
diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr
index c4e566a42d0..1152bcb0734 100644
--- a/src/test/ui/polymorphization/generators.stderr
+++ b/src/test/ui/polymorphization/generators.stderr
@@ -8,11 +8,10 @@ LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:36:5
+  --> $DIR/generators.rs:35:5
    |
 LL |   pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
    |                      - generic parameter `T` is unused
-LL |
 LL | /     || {
 LL | |
 LL | |         yield 1;
@@ -21,17 +20,10 @@ LL | |     }
    | |_____^
 
 error: item has unused generic parameters
-  --> $DIR/generators.rs:34:8
-   |
-LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-   |        ^^^^^^^^^^^ - generic parameter `T` is unused
-
-error: item has unused generic parameters
-  --> $DIR/generators.rs:62:5
+  --> $DIR/generators.rs:60:5
    |
 LL |   pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
    |                             - generic parameter `T` is unused
-LL |
 LL | /     || {
 LL | |
 LL | |         yield 1;
@@ -39,11 +31,5 @@ LL | |         2
 LL | |     }
    | |_____^
 
-error: item has unused generic parameters
-  --> $DIR/generators.rs:60:8
-   |
-LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
-   |        ^^^^^^^^^^^^       - generic parameter `T` is unused
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
index cc36f054bc3..6facc467f7a 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs
@@ -14,7 +14,7 @@ trait B {
 impl B for A {
     async fn associated(); //~ ERROR without body
     //~^ ERROR cannot be declared `async`
-    //~| ERROR incompatible type for trait
+    //~| ERROR impl has stricter requirements than trait
 }
 
 fn main() {}
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
index d3214458eac..c144060a859 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
@@ -44,25 +44,16 @@ LL |     async fn associated();
    = note: `async` trait functions are not currently supported
    = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
 
-error[E0053]: method `associated` has an incompatible type for trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:26
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
    |
 LL |     async fn associated();
-   |                          ^
-   |                          |
-   |                          checked the `Output` of this `async fn`, found opaque type
-   |                          expected `()`, found opaque type
-   |
-   = note: while checking the return type of the `async fn`
-note: type in trait
-  --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:26
-   |
+   |     ---------------------- definition of `associated` from trait
+...
 LL |     async fn associated();
-   |                          ^
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn() -> impl Future<Output = ()>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `(): Future`
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0053, E0706.
-For more information about an error, try `rustc --explain E0053`.
+Some errors have detailed explanations: E0276, E0706.
+For more information about an error, try `rustc --explain E0276`.
diff --git a/src/test/ui/save-analysis/issue-68621.rs b/src/test/ui/save-analysis/issue-68621.rs
index 96af085c5b6..30479580f11 100644
--- a/src/test/ui/save-analysis/issue-68621.rs
+++ b/src/test/ui/save-analysis/issue-68621.rs
@@ -11,7 +11,7 @@ trait Service {
 struct Struct;
 
 impl Service for Struct {
-    type Future = impl Trait; //~ ERROR: could not find defining uses
+    type Future = impl Trait; //~ ERROR: unconstrained opaque type
 }
 
 fn main() {}
diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr
index 3af6d0a3e07..4a4bf9a6996 100644
--- a/src/test/ui/save-analysis/issue-68621.stderr
+++ b/src/test/ui/save-analysis/issue-68621.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/issue-68621.rs:14:19
    |
 LL |     type Future = impl Trait;
    |                   ^^^^^^^^^^
+   |
+   = note: `Future` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 61ac7731777..570a08cb587 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -          ^^^^^^^^^^
+   |                          -                     ^^^^^^^^
    |                          |
    |                          hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here
    |
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 6f8200739b9..abdc650c68e 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -1,8 +1,8 @@
 error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                    -----      ^^^^^^^^^^
+   |                    -----                   ^^^^
    |                    |
    |                    hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs
index e72a2d8ccc6..cad7d76c6ab 100644
--- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs
+++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs
@@ -2,6 +2,7 @@ trait Bar {}
 impl Bar for u8 {}
 fn foo() -> impl Bar {
     5; //~^ ERROR the trait bound `(): Bar` is not satisfied
+    //~| ERROR the trait bound `(): Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
index d826222a06a..ba6967e78e1 100644
--- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
+++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
@@ -6,6 +6,16 @@ LL | fn foo() -> impl Bar {
 LL |     5;
    |      - consider removing this semicolon
 
-error: aborting due to previous error
+error[E0277]: the trait bound `(): Bar` is not satisfied
+  --> $DIR/impl-trait-return-trailing-semicolon.rs:3:22
+   |
+LL |   fn foo() -> impl Bar {
+   |  ______________________^
+LL | |     5;
+LL | |
+LL | | }
+   | |_^ the trait `Bar` is not implemented for `()`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/issue-81098.rs b/src/test/ui/suggestions/issue-81098.rs
index a601b5866f4..7ca7380a7be 100644
--- a/src/test/ui/suggestions/issue-81098.rs
+++ b/src/test/ui/suggestions/issue-81098.rs
@@ -1,12 +1,14 @@
 // Don't suggest removing a semicolon if the last statement isn't an expression with semicolon
 // (#81098)
 fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
+    //~^ ERROR: `()` doesn't implement `std::fmt::Display`
     fn why() {}
 }
 
 // Do it if the last statement is an expression with semicolon
 // (#54771)
 fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display`
+    //~^ ERROR: `()` doesn't implement `std::fmt::Display`
     1;
 }
 
diff --git a/src/test/ui/suggestions/issue-81098.stderr b/src/test/ui/suggestions/issue-81098.stderr
index 2a72159e577..d62526442e9 100644
--- a/src/test/ui/suggestions/issue-81098.stderr
+++ b/src/test/ui/suggestions/issue-81098.stderr
@@ -8,16 +8,43 @@ LL | fn wat() -> impl core::fmt::Display {
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 
 error[E0277]: `()` doesn't implement `std::fmt::Display`
-  --> $DIR/issue-81098.rs:9:12
+  --> $DIR/issue-81098.rs:3:37
+   |
+LL |   fn wat() -> impl core::fmt::Display {
+   |  _____________________________________^
+LL | |
+LL | |     fn why() {}
+LL | | }
+   | |_^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/issue-81098.rs:10:12
    |
 LL | fn ok() -> impl core::fmt::Display {
    |            ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
+LL |
 LL |     1;
    |      - consider removing this semicolon
    |
    = help: the trait `std::fmt::Display` is not implemented for `()`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 
-error: aborting due to 2 previous errors
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/issue-81098.rs:10:36
+   |
+LL |   fn ok() -> impl core::fmt::Display {
+   |  ____________________________________^
+LL | |
+LL | |     1;
+LL | | }
+   | |_^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/alias/issue-83613.rs b/src/test/ui/traits/alias/issue-83613.rs
index 0013d5d66f1..04320e72076 100644
--- a/src/test/ui/traits/alias/issue-83613.rs
+++ b/src/test/ui/traits/alias/issue-83613.rs
@@ -8,6 +8,6 @@ fn mk_opaque() -> OpaqueType {
 trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
-//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
 //~| ERROR cannot implement trait on type alias impl trait
 fn main() {}
diff --git a/src/test/ui/traits/alias/issue-83613.stderr b/src/test/ui/traits/alias/issue-83613.stderr
index 6a3498a3893..4f19e6607c8 100644
--- a/src/test/ui/traits/alias/issue-83613.stderr
+++ b/src/test/ui/traits/alias/issue-83613.stderr
@@ -10,13 +10,13 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
   --> $DIR/issue-83613.rs:10:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.rs b/src/test/ui/traits/pointee-tail-is-generic-errors.rs
index d081721aca2..28bc1da964d 100644
--- a/src/test/ui/traits/pointee-tail-is-generic-errors.rs
+++ b/src/test/ui/traits/pointee-tail-is-generic-errors.rs
@@ -14,7 +14,7 @@ fn a<T: ?Sized>() {
     //~^ ERROR type mismatch resolving `<T as Pointee>::Metadata == ()`
 
     is_thin::<Opaque>();
-    //~^ ERROR type mismatch resolving `<impl Debug + ?Sized as Pointee>::Metadata == ()`
+    //~^ ERROR type mismatch resolving `<Opaque as Pointee>::Metadata == ()`
 }
 
 fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.stderr b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr
index fa5fe67e53c..8456f84562f 100644
--- a/src/test/ui/traits/pointee-tail-is-generic-errors.stderr
+++ b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `is_thin`
 LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
    |                                 ^^^^^^^^^^^^^ required by this bound in `is_thin`
 
-error[E0271]: type mismatch resolving `<impl Debug + ?Sized as Pointee>::Metadata == ()`
+error[E0271]: type mismatch resolving `<Opaque as Pointee>::Metadata == ()`
   --> $DIR/pointee-tail-is-generic-errors.rs:16:5
    |
 LL | type Opaque = impl std::fmt::Debug + ?Sized;
@@ -24,13 +24,13 @@ LL |     is_thin::<Opaque>();
    |     ^^^^^^^^^^^^^^^^^ expected `()`, found associated type
    |
    = note:    expected unit type `()`
-           found associated type `<impl Debug + ?Sized as Pointee>::Metadata`
+           found associated type `<Opaque as Pointee>::Metadata`
 note: required by a bound in `is_thin`
   --> $DIR/pointee-tail-is-generic-errors.rs:20:33
    |
 LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
    |                                 ^^^^^^^^^^^^^ required by this bound in `is_thin`
-help: consider constraining the associated type `<impl Debug + ?Sized as Pointee>::Metadata` to `()`
+help: consider constraining the associated type `<Opaque as Pointee>::Metadata` to `()`
    |
 LL | type Opaque = impl std::fmt::Debug<Metadata = ()> + ?Sized;
    |                                   +++++++++++++++
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.rs b/src/test/ui/type-alias-impl-trait/argument-types.rs
index 8427b5b1fe8..185207b9800 100644
--- a/src/test/ui/type-alias-impl-trait/argument-types.rs
+++ b/src/test/ui/type-alias-impl-trait/argument-types.rs
@@ -1,14 +1,12 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
-
+// check-pass
 use std::fmt::Debug;
 
 type Foo = impl Debug;
 
-// FIXME: This should compile, but it currently doesn't
 fn foo1(mut x: Foo) {
     x = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn foo2(mut x: Foo) {
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr
deleted file mode 100644
index a87e44a048b..00000000000
--- a/src/test/ui/type-alias-impl-trait/argument-types.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/argument-types.rs:10:9
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL | fn foo1(mut x: Foo) {
-   |                --- expected due to this parameter type
-LL |     x = 22_u32;
-   |         ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
index 4a49d6e4ab8..0664275b2ad 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
@@ -2,15 +2,15 @@ error[E0277]: `Rc<u32>` cannot be sent between threads safely
   --> $DIR/auto-trait-leakage2.rs:17:13
    |
 LL |     type Foo = impl std::fmt::Debug;
-   |                -------------------- within this `impl Debug`
+   |                -------------------- within this `Foo`
 ...
 LL |     is_send(m::foo());
    |     ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely
    |     |
    |     required by a bound introduced by this call
    |
-   = help: within `impl Debug`, the trait `Send` is not implemented for `Rc<u32>`
-   = note: required because it appears within the type `impl Debug`
+   = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
+   = note: required because it appears within the type `Foo`
 note: required by a bound in `is_send`
   --> $DIR/auto-trait-leakage2.rs:14:15
    |
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
index 5fb7a9473d3..b456b1445e7 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
@@ -6,6 +6,7 @@
 mod m {
     type Foo = impl std::fmt::Debug;
     //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+    //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
 
     pub fn foo() -> Foo {
         22_u32
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index c0147e56c93..4c44875b4a5 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -5,11 +5,10 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:15:9
+  --> $DIR/auto-trait-leakage3.rs:15:5
    |
-LL |         is_send(foo());
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/auto-trait-leakage3.rs:6:1
@@ -17,6 +16,24 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error: aborting due to previous error
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/auto-trait-leakage3.rs:7:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/auto-trait-leakage3.rs:15:5
+   |
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/auto-trait-leakage3.rs:6:1
+   |
+LL | mod m {
+   | ^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
index cee8186dd8f..4d2890b5de5 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -7,13 +7,12 @@ trait TraitWithAssoc {
 }
 
 type Foo<V> = impl Trait<V>;
-//~^ ERROR could not find defining uses
 
 trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-    //~^ ERROR non-defining opaque type use in defining scope
     ()
+    //~^ ERROR non-defining opaque type use
 }
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
index 03e696fe898..c405b1f6af2 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/bound_reduction2.rs:16:46
+  --> $DIR/bound_reduction2.rs:16:5
    |
-LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-   |                                              ^^^^^^^^^^^^^
+LL |     ()
+   |     ^^
    |
 note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
   --> $DIR/bound_reduction2.rs:9:10
@@ -10,11 +10,5 @@ note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
 LL | type Foo<V> = impl Trait<V>;
    |          ^
 
-error: could not find defining uses
-  --> $DIR/bound_reduction2.rs:9:15
-   |
-LL | type Foo<V> = impl Trait<V>;
-   |               ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs
index eecef2338c1..83d22161e4e 100644
--- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs
+++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs
@@ -4,11 +4,11 @@
 #![feature(type_alias_impl_trait)]
 
 type X<'a> = impl Into<&'static str> + From<&'a str>;
-//~^ ERROR mismatched types
 
 fn f<'a: 'static>(t: &'a str) -> X<'a> {
     //~^ WARNING unnecessary lifetime parameter
     t
+    //~^ ERROR non-defining opaque type use
 }
 
 fn extend_lt<'a>(o: &'a str) -> &'static str {
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
index da9f81d6bd3..d87ef2ec79c 100644
--- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
+++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
@@ -1,26 +1,19 @@
 warning: unnecessary lifetime parameter `'a`
-  --> $DIR/bounds-are-checked.rs:9:6
+  --> $DIR/bounds-are-checked.rs:8:6
    |
 LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
    |      ^^^^^^^^^^^
    |
    = help: you can use the `'static` lifetime directly, in place of `'a`
 
-error[E0308]: mismatched types
-  --> $DIR/bounds-are-checked.rs:6:14
+error: non-defining opaque type use in defining scope
+  --> $DIR/bounds-are-checked.rs:10:5
    |
 LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
-   |
-   = note: expected trait `From<&'a str>`
-              found trait `From<&'static str>`
-note: the lifetime `'a` as defined here...
-  --> $DIR/bounds-are-checked.rs:6:8
-   |
-LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
-   |        ^^
-   = note: ...does not necessarily outlive the static lifetime
+   |        -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL |     t
+   |     ^
 
 error: aborting due to previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.rs b/src/test/ui/type-alias-impl-trait/closures_in_branches.rs
new file mode 100644
index 00000000000..a1a9401acc2
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.rs
@@ -0,0 +1,31 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::ops::FnOnce(String) -> usize;
+
+fn foo(b: bool) -> Foo {
+    if b {
+        |x| x.len()
+    } else {
+        panic!()
+    }
+}
+
+
+type Foo1 = impl std::ops::FnOnce(String) -> usize;
+fn foo1(b: bool) -> Foo1 {
+    |x| x.len()
+}
+
+fn bar(b: bool) -> impl std::ops::FnOnce(String) -> usize {
+    if b {
+        |x| x.len() //~ ERROR type annotations needed
+    } else {
+        panic!()
+    }
+}
+
+fn bar1(b: bool) -> impl std::ops::FnOnce(String) -> usize {
+    |x| x.len()
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
new file mode 100644
index 00000000000..cfa4a4b9d20
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/closures_in_branches.rs:21:10
+   |
+LL |         |x| x.len()
+   |          ^ 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/type-alias-impl-trait/declared_but_never_defined.rs b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs
index c4bf56a9197..6febd07157a 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs
+++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.rs
@@ -3,4 +3,4 @@
 fn main() {}
 
 // declared but never defined
-type Bar = impl std::fmt::Debug; //~ ERROR could not find defining uses
+type Bar = impl std::fmt::Debug; //~ ERROR unconstrained opaque type
diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
index 21c2e8a9db6..60bc24320a3 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
+++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/declared_but_never_defined.rs:6:12
    |
 LL | type Bar = impl std::fmt::Debug;
    |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs
index 7ea517eb734..5bda5f0fcea 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs
+++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs
@@ -4,7 +4,7 @@ fn main() {}
 
 mod boo {
     // declared in module but not defined inside of it
-    pub type Boo = impl ::std::fmt::Debug; //~ ERROR could not find defining uses
+    pub type Boo = impl ::std::fmt::Debug; //~ ERROR unconstrained opaque type
 }
 
 fn bomp() -> boo::Boo {
diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
index 0b4c262bbb4..fbfa0ccf1e8 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
+++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/declared_but_not_defined_in_scope.rs:7:20
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Boo` must be used in combination with a concrete type within the same module
 
 error[E0308]: mismatched types
   --> $DIR/declared_but_not_defined_in_scope.rs:11:5
@@ -11,11 +13,11 @@ LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ---------------------- the expected opaque type
 ...
 LL | fn bomp() -> boo::Boo {
-   |              -------- expected `impl Debug` because of return type
+   |              -------- expected `Boo` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `impl Debug`
+   = note: expected opaque type `Boo`
                 found reference `&'static str`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses.rs
index 272af7a5204..4505c4d9524 100644
--- a/src/test/ui/type-alias-impl-trait/different_defining_uses.rs
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses.rs
@@ -10,6 +10,6 @@ fn foo() -> Foo {
 }
 
 fn bar() -> Foo {
-    //~^ ERROR concrete type differs from previous
     42i32
+    //~^ ERROR concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr
index eaa716bc71c..a8b4cd7afe8 100644
--- a/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses.rs:12:1
+  --> $DIR/different_defining_uses.rs:13:5
    |
-LL | fn bar() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `i32`
+LL |     42i32
+   |     ^^^^^ expected `&'static str`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses.rs:8:1
+  --> $DIR/different_defining_uses.rs:9:5
    |
-LL | fn foo() -> Foo {
-   | ^^^^^^^^^^^^^^^
+LL |     ""
+   |     ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
index 95cbcfec2dc..7740f774ebc 100644
--- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
@@ -1,5 +1,5 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 fn main() {}
 
 // two definitions with different types
@@ -10,11 +10,9 @@ fn foo() -> Foo {
 }
 
 fn bar() -> Foo {
-    //~^ ERROR concrete type differs from previous
     panic!()
 }
 
 fn boo() -> Foo {
-    //~^ ERROR concrete type differs from previous
     loop {}
 }
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
deleted file mode 100644
index 6274029e4f5..00000000000
--- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type.rs:12:1
-   |
-LL | fn bar() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
-   |
-note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:8:1
-   |
-LL | fn foo() -> Foo {
-   | ^^^^^^^^^^^^^^^
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type.rs:17:1
-   |
-LL | fn boo() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `&'static str`, got `()`
-   |
-note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:8:1
-   |
-LL | fn foo() -> Foo {
-   | ^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
index d0001976d65..4f424b8c665 100644
--- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
+++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
@@ -8,8 +8,8 @@ fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
 }
 
 fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
-    //~^ ERROR: concrete type differs from previous defining opaque type use
     b
+    //~^ ERROR: concrete type differs from previous defining opaque type use
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
index 9493a59cf1e..0c50a84e894 100644
--- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
+++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_lifetimes_defining_uses.rs:10:1
+  --> $DIR/different_lifetimes_defining_uses.rs:11:5
    |
-LL | fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32`
+LL |     b
+   |     ^ expected `&'a u32`, got `&'b u32`
    |
 note: previous use here
-  --> $DIR/different_lifetimes_defining_uses.rs:6:1
+  --> $DIR/different_lifetimes_defining_uses.rs:7:5
    |
-LL | fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     a
+   |     ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/fallback.rs b/src/test/ui/type-alias-impl-trait/fallback.rs
index fe1ca2230da..d7e93335f47 100644
--- a/src/test/ui/type-alias-impl-trait/fallback.rs
+++ b/src/test/ui/type-alias-impl-trait/fallback.rs
@@ -1,5 +1,5 @@
-// Tests that we correctly handle the instantiated
-// inference variable being completely unconstrained.
+// Tests that we correctly handle opaque types being used opaquely,
+// even within their defining scope.
 //
 // check-pass
 #![feature(type_alias_impl_trait)]
diff --git a/src/test/ui/type-alias-impl-trait/field-types.rs b/src/test/ui/type-alias-impl-trait/field-types.rs
index 91494a82d0f..d99ed58127b 100644
--- a/src/test/ui/type-alias-impl-trait/field-types.rs
+++ b/src/test/ui/type-alias-impl-trait/field-types.rs
@@ -1,12 +1,11 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME This should compile, but it currently doesn't
+// check-pass
 
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
 
 struct Bar {
     foo: Foo,
@@ -14,7 +13,6 @@ struct Bar {
 
 fn bar() -> Bar {
     Bar { foo: "foo" }
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/field-types.stderr b/src/test/ui/type-alias-impl-trait/field-types.stderr
deleted file mode 100644
index 18c2abbdf37..00000000000
--- a/src/test/ui/type-alias-impl-trait/field-types.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/field-types.rs:16:16
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     Bar { foo: "foo" }
-   |                ^^^^^ expected opaque type, found `&str`
-   |
-   = note: expected opaque type `impl Debug`
-                found reference `&'static str`
-
-error: could not find defining uses
-  --> $DIR/field-types.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs
index 07535130758..8b683ad2828 100644
--- a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.rs
@@ -9,6 +9,6 @@ fn my_iter<T>(t: T) -> MyIter<T> {
 }
 
 fn my_iter2<T>(t: T) -> MyIter<T> {
-    //~^ ERROR concrete type differs from previous
     Some(t).into_iter()
+    //~^ ERROR concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
index f8a058170e3..47ac3346259 100644
--- a/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_different_defining_uses.rs:11:1
+  --> $DIR/generic_different_defining_uses.rs:12:5
    |
-LL | fn my_iter2<T>(t: T) -> MyIter<T> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
+LL |     Some(t).into_iter()
+   |     ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
-  --> $DIR/generic_different_defining_uses.rs:7:1
+  --> $DIR/generic_different_defining_uses.rs:8:5
    |
-LL | fn my_iter<T>(t: T) -> MyIter<T> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     std::iter::once(t)
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
index 885aae619d6..c9b9e128f88 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
@@ -3,9 +3,9 @@
 fn main() {}
 
 type Two<'a, 'b> = impl std::fmt::Debug;
-//~^ ERROR could not find defining uses
+
 
 fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-    //~^ ERROR non-defining opaque type use
     t
+    //~^ ERROR non-defining opaque type use
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
index b99c6a51f4b..222aaea78d9 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_lifetime_param.rs:8:26
+  --> $DIR/generic_duplicate_lifetime_param.rs:9:5
    |
-LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-   |                          ^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: lifetime used multiple times
   --> $DIR/generic_duplicate_lifetime_param.rs:5:10
@@ -10,11 +10,5 @@ note: lifetime used multiple times
 LL | type Two<'a, 'b> = impl std::fmt::Debug;
    |          ^^  ^^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_lifetime_param.rs:5:20
-   |
-LL | type Two<'a, 'b> = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index 33cd2f6ba07..093c1c23186 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -6,23 +6,23 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type TwoTys<T, U> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type TwoLifetimes<'a, 'b> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type TwoConsts<const X: usize, const Y: usize> = impl Debug;
-//~^ ERROR could not find defining uses
+
 
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
+    //~^ ERROR non-defining opaque type use in defining scope
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 52c60d1777e..922e41e0f68 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:15:30
+  --> $DIR/generic_duplicate_param_use.rs:16:5
    |
-LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-   |                              ^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: type used multiple times
   --> $DIR/generic_duplicate_param_use.rs:8:13
@@ -10,17 +10,11 @@ note: type used multiple times
 LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:8:21
-   |
-LL | type TwoTys<T, U> = impl Debug;
-   |                     ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:20:36
+  --> $DIR/generic_duplicate_param_use.rs:21:5
    |
-LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-   |                                    ^^^^^^^^^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: lifetime used multiple times
   --> $DIR/generic_duplicate_param_use.rs:10:19
@@ -28,17 +22,11 @@ note: lifetime used multiple times
 LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                   ^^  ^^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:10:29
-   |
-LL | type TwoLifetimes<'a, 'b> = impl Debug;
-   |                             ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:25:50
+  --> $DIR/generic_duplicate_param_use.rs:26:5
    |
-LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-   |                                                  ^^^^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
 note: constant used multiple times
   --> $DIR/generic_duplicate_param_use.rs:12:22
@@ -46,11 +34,5 @@ note: constant used multiple times
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                      ^               ^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:12:50
-   |
-LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
-   |                                                  ^^^^^^^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
index 04fb57b39c0..81bf9770d02 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
@@ -8,11 +8,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index fca9b70d184..84aa260b099 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -1,15 +1,3 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use2.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use2.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use2.rs:8:18
    |
@@ -21,6 +9,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-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/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
index 1a755d39026..7747626d96d 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
@@ -8,16 +8,11 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
 }
 
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
-    //~^ ERROR concrete type differs from previous defining opaque type use
     u
+    //~^ ERROR concrete type differs from previous defining opaque type use
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
index 90b04c043a0..88c450704bf 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
@@ -1,26 +1,14 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use3.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use3.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use3.rs:20:1
+  --> $DIR/generic_duplicate_param_use3.rs:16:5
    |
-LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U`
+LL |     u
+   |     ^ expected `T`, got `U`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use3.rs:16:1
+  --> $DIR/generic_duplicate_param_use3.rs:12:5
    |
-LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     t
+   |     ^
 
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use3.rs:8:18
@@ -33,6 +21,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
index 50d95c83d58..aee2550e907 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
@@ -8,11 +8,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `U` doesn't implement `Debug`
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    t
-}
-
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
     u
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index c4be2fa83f1..0491d61030e 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -1,15 +1,3 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use4.rs:11:27
-   |
-LL | fn one<T: Debug>(t: T) -> Two<T, T> {
-   |                           ^^^^^^^^^
-   |
-note: type used multiple times
-  --> $DIR/generic_duplicate_param_use4.rs:8:10
-   |
-LL | type Two<T, U> = impl Debug;
-   |          ^  ^
-
 error[E0277]: `U` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use4.rs:8:18
    |
@@ -21,6 +9,6 @@ help: consider restricting type parameter `U`
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
    |              +++++++++++++++++
 
-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/type-alias-impl-trait/generic_duplicate_param_use5.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
index dd2f202cf5d..03bd00a039d 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
@@ -14,6 +14,6 @@ fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 }
 
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    //~^ concrete type differs from previous
     (u, t)
+    //~^ concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
index 6cc6b35668c..d46a3ebe175 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use5.rs:16:1
+  --> $DIR/generic_duplicate_param_use5.rs:17:5
    |
-LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)`
+LL |     (u, t)
+   |     ^^^^^^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use5.rs:12:1
+  --> $DIR/generic_duplicate_param_use5.rs:13:5
    |
-LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (t, u)
+   |     ^^^^^^
 
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use5.rs:8:18
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
index d54d3cd62e0..a8c801dc887 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
@@ -13,6 +13,6 @@ fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
 }
 
 fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    //~^ ERROR concrete type differs from previous
     (u, t)
+    //~^ ERROR concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
index e7520988e34..7e89b574b5c 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use6.rs:15:1
+  --> $DIR/generic_duplicate_param_use6.rs:16:5
    |
-LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)`
+LL |     (u, t)
+   |     ^^^^^^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use6.rs:11:1
+  --> $DIR/generic_duplicate_param_use6.rs:12:5
    |
-LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (t, t)
+   |     ^^^^^^
 
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use6.rs:8:18
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
index 4a723b64cdc..57527e758db 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
@@ -12,6 +12,6 @@ fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
 }
 
 fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-    //~^ concrete type differs from previous
     (u, 4u32)
+    //~^ concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
index 44bdbdc95cc..1a6ec3aec14 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use8.rs:14:1
+  --> $DIR/generic_duplicate_param_use8.rs:15:5
    |
-LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
+LL |     (u, 4u32)
+   |     ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use8.rs:10:1
+  --> $DIR/generic_duplicate_param_use8.rs:11:5
    |
-LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (t, 4u32)
+   |     ^^^^^^^^^
 
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/generic_duplicate_param_use8.rs:7:18
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
index 4baf198b12f..5878ad92698 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
@@ -19,5 +19,5 @@ fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
 }
 
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    (t, u, 42) //~^ ERROR concrete type differs from previous
+    (t, u, 42) //~ ERROR concrete type differs from previous
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
index 43471f980b2..ef7573246af 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use9.rs:21:1
+  --> $DIR/generic_duplicate_param_use9.rs:22:5
    |
-LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
+LL |     (t, u, 42)
+   |     ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use9.rs:17:1
+  --> $DIR/generic_duplicate_param_use9.rs:18:5
    |
-LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (t, u, T::BAR)
+   |     ^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `A: Foo` is not satisfied
   --> $DIR/generic_duplicate_param_use9.rs:7:18
diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
index cf43085877f..f39741a6a62 100644
--- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -5,25 +5,25 @@ use std::fmt::Debug;
 fn main() {}
 
 type OneTy<T> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type OneLifetime<'a> = impl Debug;
-//~^ ERROR could not find defining uses
+
 type OneConst<const X: usize> = impl Debug;
-//~^ ERROR could not find defining uses
+
 
 // Not defining uses, because they doesn't define *all* possible generics.
 
 fn concrete_ty() -> OneTy<u32> {
-    //~^ ERROR non-defining opaque type use in defining scope
     5u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn concrete_lifetime() -> OneLifetime<'static> {
-    //~^ ERROR non-defining opaque type use in defining scope
     6u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
 
 fn concrete_const() -> OneConst<{ 123 }> {
-    //~^ ERROR non-defining opaque type use in defining scope
     7u32
+    //~^ ERROR non-defining opaque type use in defining scope
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index 3aa42a25484..36694900c17 100644
--- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:16:21
+  --> $DIR/generic_nondefining_use.rs:17:5
    |
-LL | fn concrete_ty() -> OneTy<u32> {
-   |                     ^^^^^^^^^^
+LL |     5u32
+   |     ^^^^
    |
 note: used non-generic type `u32` for generic parameter
   --> $DIR/generic_nondefining_use.rs:7:12
@@ -10,32 +10,20 @@ note: used non-generic type `u32` for generic parameter
 LL | type OneTy<T> = impl Debug;
    |            ^
 
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:7:17
-   |
-LL | type OneTy<T> = impl Debug;
-   |                 ^^^^^^^^^^
-
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:21:27
+  --> $DIR/generic_nondefining_use.rs:22:5
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
 ...
-LL | fn concrete_lifetime() -> OneLifetime<'static> {
-   |                           ^^^^^^^^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:9:24
-   |
-LL | type OneLifetime<'a> = impl Debug;
-   |                        ^^^^^^^^^^
+LL |     6u32
+   |     ^^^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:26:24
+  --> $DIR/generic_nondefining_use.rs:27:5
    |
-LL | fn concrete_const() -> OneConst<{ 123 }> {
-   |                        ^^^^^^^^^^^^^^^^^
+LL |     7u32
+   |     ^^^^
    |
 note: used non-generic constant `123_usize` for generic parameter
   --> $DIR/generic_nondefining_use.rs:11:21
@@ -43,11 +31,5 @@ note: used non-generic constant `123_usize` for generic parameter
 LL | type OneConst<const X: usize> = impl Debug;
    |                     ^
 
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:11:33
-   |
-LL | type OneConst<const X: usize> = impl Debug;
-   |                                 ^^^^^^^^^^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.rs b/src/test/ui/type-alias-impl-trait/generic_not_used.rs
index dd6300a64f4..c70f473cff5 100644
--- a/src/test/ui/type-alias-impl-trait/generic_not_used.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_not_used.rs
@@ -6,6 +6,6 @@ type WrongGeneric<T: 'static> = impl 'static;
 //~^ ERROR: at least one trait must be specified
 
 fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
-    //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
     v
+    //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr
index 8015ff7eded..fd720239a52 100644
--- a/src/test/ui/type-alias-impl-trait/generic_not_used.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_not_used.stderr
@@ -5,14 +5,10 @@ LL | type WrongGeneric<T: 'static> = impl 'static;
    |                                 ^^^^^^^^^^^^
 
 error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/generic_not_used.rs:8:73
+  --> $DIR/generic_not_used.rs:9:5
    |
-LL |   fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
-   |  _________________________________________________________________________^
-LL | |
-LL | |     v
-LL | | }
-   | |_^
+LL |     v
+   |     ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
index f4e1de8e50f..dc85db66d32 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
@@ -1,41 +1,29 @@
 error: at least one trait must be specified
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:24
    |
 LL | type WrongGeneric<T> = impl 'static;
    |                        ^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: non-defining opaque type use in defining scope
   --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
    |
 LL |     let z: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-...
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ------------ the found opaque type
-   |
-   = note:     expected type `i32`
-           found opaque type `impl Sized`
-
-error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:30
+   |                  ^
    |
-LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-   |                              ^^^^^^^^^^^^^^^
+note: used non-generic type `&'static i32` for generic parameter
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:19
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
+LL | type WrongGeneric<T> = impl 'static;
+   |                   ^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:5
    |
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ^^^^^^^^^^^^
+LL |     t
+   |     ^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0308, E0310.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
index 78d25e30e03..cb90776472b 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -3,13 +3,14 @@
 fn main() {
     let y = 42;
     let x = wrong_generic(&y);
-    let z: i32 = x; //~ ERROR mismatched types
+    let z: i32 = x;
+    //~^ ERROR non-defining opaque type use
 }
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-    //~^ ERROR the parameter type `T` may not live long enough
     t
+    //~^ ERROR the parameter type `T` may not live long enough
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 568784372e5..15ec2eed3da 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -1,32 +1,29 @@
 error: at least one trait must be specified
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:24
    |
 LL | type WrongGeneric<T> = impl 'static;
    |                        ^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: non-defining opaque type use in defining scope
   --> $DIR/generic_type_does_not_live_long_enough.rs:6:18
    |
 LL |     let z: i32 = x;
-   |            ---   ^ expected `i32`, found opaque type
-   |            |
-   |            expected due to this
-...
-LL | type WrongGeneric<T> = impl 'static;
-   |                        ------------ the found opaque type
+   |                  ^
+   |
+note: used non-generic type `&'static i32` for generic parameter
+  --> $DIR/generic_type_does_not_live_long_enough.rs:10:19
    |
-   = note:     expected type `i32`
-           found opaque type `impl Sized`
+LL | type WrongGeneric<T> = impl 'static;
+   |                   ^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:12:30
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:5
    |
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-   |                  -           ^^^^^^^^^^^^^^^ ...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 |     t
+   |     ^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0308, E0310.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
index c781e200bf8..608572978a3 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
@@ -3,7 +3,8 @@
 
 mod m {
     type Foo = impl std::fmt::Debug;
-    //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+    //~^ ERROR cycle detected
+    //~| ERROR cycle detected
 
     // Cycle: error today, but it'd be nice if it eventually worked
 
@@ -17,7 +18,6 @@ mod m {
 
     fn baz() {
         let f: Foo = 22_u32;
-        //~^ ERROR: mismatched types [E0308]
     }
 
     fn is_send<T: Send>(_: T) {}
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
index e1212466477..3ed86fae8a1 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -5,11 +5,10 @@ LL |     type Foo = impl std::fmt::Debug;
    |                ^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:15:9
+  --> $DIR/inference-cycle.rs:15:5
    |
-LL |         is_send(foo()); // Today: error
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
    = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in module `m`
   --> $DIR/inference-cycle.rs:4:1
@@ -17,21 +16,24 @@ note: cycle used when checking item types in module `m`
 LL | mod m {
    | ^^^^^
 
-error[E0308]: mismatched types
-  --> $DIR/inference-cycle.rs:19:22
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/inference-cycle.rs:5:16
    |
 LL |     type Foo = impl std::fmt::Debug;
-   |                -------------------- the expected opaque type
-...
-LL |         let f: Foo = 22_u32;
-   |                ---   ^^^^^^ expected opaque type, found `u32`
-   |                |
-   |                expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/inference-cycle.rs:15:5
+   |
+LL |     pub fn bar() {
+   |     ^^^^^^^^^^^^
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/inference-cycle.rs:4:1
+   |
+LL | mod m {
+   | ^^^^^
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0391.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
index d82050e263e..4c5fd22556a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-52843-closure-constrain.rs:10:16
+  --> $DIR/issue-52843-closure-constrain.rs:10:31
    |
 LL |     let null = || -> Opaque { 0 };
-   |                ^^^^^^^^^^^^^^^^^^ expected `String`, got `i32`
+   |                               ^ expected `String`, got `i32`
    |
 note: previous use here
-  --> $DIR/issue-52843-closure-constrain.rs:9:5
+  --> $DIR/issue-52843-closure-constrain.rs:9:30
    |
 LL |     fn _unused() -> Opaque { String::new() }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs
index f936dc42f13..9c1cbf926f5 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53598.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53598.rs
@@ -17,8 +17,8 @@ impl Foo for S2 {
     type Item = impl Debug;
 
     fn foo<T: Debug>(_: T) -> Self::Item {
-        //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         S::<T>(Default::default())
+        //~^ 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/type-alias-impl-trait/issue-53598.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.stderr
index 9971c7e0e20..f8b8201e2eb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53598.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53598.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-53598.rs:19:42
+  --> $DIR/issue-53598.rs:20:9
    |
-LL |       fn foo<T: Debug>(_: T) -> Self::Item {
-   |  __________________________________________^
-LL | |
-LL | |         S::<T>(Default::default())
-LL | |     }
-   | |_____^
+LL |         S::<T>(Default::default())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
index a4ccae4eb7e..91daa65d656 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
@@ -1,38 +1,26 @@
-error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
-error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
-   |
-LL |         |x| x
-   |         ^^^^^
-
 error[E0308]: mismatched types
-  --> $DIR/issue-57611-trait-alias.rs:17:16
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+LL |         |x| x
+   |         ^^^^^ one type is more general than the other
    |
    = note: expected type `for<'r> Fn<(&'r X,)>`
-              found type `Fn<(&'static X,)>`
+              found type `Fn<(&X,)>`
 note: this closure does not fulfill the lifetime requirements
-  --> $DIR/issue-57611-trait-alias.rs:21:9
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:17:16
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
-LL |     type Bar = impl Baz<Self, Self>;
-   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+LL |         |x| x
+   |         ^^^^^ implementation of `FnOnce` is not general enough
    |
-   = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`...
-   = note: ...but it actually implements `FnOnce<(&'static X,)>`
+   = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
index 625e46b6bc0..7c6e7642484 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -17,8 +17,8 @@ impl Foo for X {
     type Bar = impl Baz<Self, Self>;
 
     fn bar(&self) -> Self::Bar {
-        //~^ ERROR implementation of `FnOnce` is not general enough
         |x| x
+        //~^ ERROR implementation of `FnOnce` is not general enough
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
index 54d237159d8..45329ea292d 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
@@ -1,8 +1,8 @@
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57611-trait-alias.rs:19:22
+  --> $DIR/issue-57611-trait-alias.rs:20:9
    |
-LL |     fn bar(&self) -> Self::Bar {
-   |                      ^^^^^^^^^ implementation of `FnOnce` is not general enough
+LL |         |x| x
+   |         ^^^^^ implementation of `FnOnce` is not general enough
    |
    = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2`
diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs
index 13a6b7c2f7c..48458938702 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57700.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57700.rs
@@ -13,8 +13,8 @@ impl<C> Foo for C {
     type Bar = impl Foo;
 
     fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
         self
+        //~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.stderr
index b2e3f46f1f5..31b6df5d4c3 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57700.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57700.stderr
@@ -1,12 +1,8 @@
 error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-57700.rs:15:58
+  --> $DIR/issue-57700.rs:16:9
    |
-LL |       fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
-   |  __________________________________________________________^
-LL | |
-LL | |         self
-LL | |     }
-   | |_____^
+LL |         self
+   |         ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-58951-2.rs b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs
new file mode 100644
index 00000000000..e4ba7f8e2a6
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-58951-2.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+mod defining_use_scope {
+    pub type A = impl Iterator;
+
+    pub fn def_a() -> A {
+        0..1
+    }
+}
+use defining_use_scope::*;
+
+pub fn use_a() {
+    def_a().map(|x| x);
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs
index badf35484f3..9a40f3d9b64 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs
@@ -9,7 +9,6 @@ impl Bug for &() {
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR the trait bound `(): Bug` is not satisfied
-    //~| ERROR non-defining opaque type use in defining scope
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
index dc8a381aece..5fec078956b 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -11,21 +11,12 @@ error[E0277]: the trait bound `(): Bug` is not satisfied
   --> $DIR/issue-60371.rs:10:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
-   |                                        ^ the trait `Bug` is not implemented for `()`
+   |                                        ^^ the trait `Bug` is not implemented for `()`
    |
    = help: the following implementations were found:
              <&() as Bug>
 
-error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60371.rs:10:37
-   |
-LL | impl Bug for &() {
-   |              - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-...
-LL |     const FUN: fn() -> Self::Item = || ();
-   |                                     ^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs
index 44dcec2c3da..4fc7679311a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -6,7 +6,6 @@ trait IterBits {
 }
 
 type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-//~^ ERROR could not find defining uses
 
 impl<T: Copy, E> IterBits for T
 where
@@ -18,8 +17,8 @@ where
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-        //~^ ERROR non-defining opaque type use in defining scope
         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+        //~^ ERROR non-defining opaque type use in defining scope
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
index 6b73fbef011..bbc93657be3 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:20:34
+  --> $DIR/issue-60564.rs:20:9
    |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^
+LL |         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: used non-generic type `u8` for generic parameter
   --> $DIR/issue-60564.rs:8:25
@@ -10,11 +10,5 @@ note: used non-generic type `u8` for generic parameter
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         ^
 
-error: could not find defining uses
-  --> $DIR/issue-60564.rs:8:30
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.rs b/src/test/ui/type-alias-impl-trait/issue-63279.rs
index 875cce4df23..057a908bbee 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs
@@ -5,7 +5,10 @@
 type Closure = impl FnOnce();
 
 fn c() -> Closure {
-    || -> Closure { || () } //~ ERROR: mismatched types
+    || -> Closure { || () }
+    //~^ ERROR: mismatched types
+    //~| ERROR: mismatched types
+    //~| ERROR: expected a `FnOnce<()>` closure, found `()`
 }
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr
index 5fde8c2ef1e..bcc9c57f91c 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,17 +1,36 @@
+error[E0277]: expected a `FnOnce<()>` closure, found `()`
+  --> $DIR/issue-63279.rs:8:11
+   |
+LL |     || -> Closure { || () }
+   |           ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `()`
+   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-63279.rs:8:21
+   |
+LL |     || -> Closure { || () }
+   |                     ^^^^^ expected `()`, found closure
+   |
+   = note: expected unit type `()`
+                found closure `[closure@$DIR/issue-63279.rs:8:21: 8:26]`
+
 error[E0308]: mismatched types
   --> $DIR/issue-63279.rs:8:5
    |
 LL | type Closure = impl FnOnce();
-   |                ------------- the found opaque type
-...
+   |                ------------- the expected opaque type
+LL | 
+LL | fn c() -> Closure {
+   |           ------- expected `Closure` because of return type
 LL |     || -> Closure { || () }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure
    |
-   = note: expected type `[closure@$DIR/issue-63279.rs:8:21: 8:26]`
-           found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]`
-   = note: no two closures, even if identical, have the same type
-   = help: consider boxing your closure and/or using it as a trait object
+   = note: expected opaque type `Closure`
+                  found closure `[closure@$DIR/issue-63279.rs:8:5: 8:28]`
 
-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: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs
index 9f617153e3f..7066a0535e1 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63355.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs
@@ -1,5 +1,5 @@
 #![feature(type_alias_impl_trait)]
-#![allow(incomplete_features)]
+// check-pass
 
 pub trait Foo {}
 
@@ -27,11 +27,8 @@ impl Bar for () {
     }
 }
 
-// FIXME(#86731): The below is illegal use of `type_alias_impl_trait`
-// but the compiler doesn't report it, we should fix it.
 pub type FooImpl = impl Foo;
 pub type BarImpl = impl Bar<Foo = FooImpl>;
-//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()`
 
 impl Baz for () {
     type Foo = FooImpl;
diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr
deleted file mode 100644
index 2dbd5a55a62..00000000000
--- a/src/test/ui/type-alias-impl-trait/issue-63355.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()`
-  --> $DIR/issue-63355.rs:33:20
-   |
-LL | pub type FooImpl = impl Foo;
-   |                    -------- the found opaque type
-LL | pub type BarImpl = impl Bar<Foo = FooImpl>;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()`
-   |
-note: expected this to be `()`
-  --> $DIR/issue-63355.rs:23:16
-   |
-LL |     type Foo = FooImpl;
-   |                ^^^^^^^
-   = note: expected unit type `()`
-            found opaque type `impl Foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
index 2e6354088ac..5223fb1c702 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
@@ -5,7 +5,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
-//~^ ERROR could not find defining uses
+
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR non-defining opaque type use in defining scope
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
index 721f99a3f0d..7fb9a0c410e 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use-2.rs:9:15
+  --> $DIR/issue-68368-non-defining-use-2.rs:9:29
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^
+   |                             ^^
    |
 note: used non-generic type `()` for generic parameter
   --> $DIR/issue-68368-non-defining-use-2.rs:7:16
@@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter
 LL | type Alias<'a, U> = impl Trait<U>;
    |                ^
 
-error: could not find defining uses
-  --> $DIR/issue-68368-non-defining-use-2.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
index 3addd8dcc4f..b50462bf237 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
@@ -5,7 +5,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
-//~^ ERROR could not find defining uses
+
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR non-defining opaque type use in defining scope
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
index f5b8fccf65d..8059621b61a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -1,8 +1,8 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use.rs:9:15
+  --> $DIR/issue-68368-non-defining-use.rs:9:29
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^
+   |                             ^^
    |
 note: used non-generic type `()` for generic parameter
   --> $DIR/issue-68368-non-defining-use.rs:7:16
@@ -10,11 +10,5 @@ note: used non-generic type `()` for generic parameter
 LL | type Alias<'a, U> = impl Trait<U>;
    |                ^
 
-error: could not find defining uses
-  --> $DIR/issue-68368-non-defining-use.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-74280.stderr b/src/test/ui/type-alias-impl-trait/issue-74280.stderr
index f6b369dd8d5..7a22b360a31 100644
--- a/src/test/ui/type-alias-impl-trait/issue-74280.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-74280.stderr
@@ -1,8 +1,17 @@
 error[E0308]: mismatched types
   --> $DIR/issue-74280.rs:9:5
    |
+LL | type Test = impl Copy;
+   |             --------- the expected opaque type
+LL | 
+LL | fn test() -> Test {
+   |              ---- expected `Test` because of return type
+LL |     let y = || -> Test { () };
 LL |     7
    |     ^ expected `()`, found integer
+   |
+   = note: expected opaque type `Test`
+                     found type `{integer}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-77179.stderr b/src/test/ui/type-alias-impl-trait/issue-77179.stderr
index 15205ba9b41..053546e4b92 100644
--- a/src/test/ui/type-alias-impl-trait/issue-77179.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-77179.stderr
@@ -5,7 +5,7 @@ LL | fn test() -> Pointer<_> {
    |              --------^-
    |              |       |
    |              |       not allowed in type signatures
-   |              help: replace with the correct return type: `Box<i32>`
+   |              help: replace with the correct return type: `Pointer<i32>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-93411.rs b/src/test/ui/type-alias-impl-trait/issue-93411.rs
new file mode 100644
index 00000000000..1f8c789267d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-93411.rs
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+
+// this test used to stack overflow due to infinite recursion.
+// check-pass
+// compile-flags: --edition=2018
+
+use std::future::Future;
+
+fn main() {
+    let _ = move || async move {
+        let value = 0u8;
+        blah(&value).await;
+    };
+}
+
+type BlahFut<'a> = impl Future<Output = ()> + Send + 'a;
+fn blah<'a>(_value: &'a u8) -> BlahFut<'a> {
+    async {}
+}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
new file mode 100644
index 00000000000..b887fcf3083
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/73481
+// This test used to cause unsoundness, since one of the two possible
+// resolutions was chosen at random instead of erroring due to conflicts.
+
+#![feature(type_alias_impl_trait)]
+
+type Y<A, B> = impl std::fmt::Debug;
+
+fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
+    (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
new file mode 100644
index 00000000000..27811700912
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
@@ -0,0 +1,11 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5
+   |
+LL |     (42_i64, 60)
+   |     ^^^^^^^^^^^^
+   |     |
+   |     expected `i64`, got `i32`
+   |     this expression supplies two conflicting concrete types for the same opaque type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
new file mode 100644
index 00000000000..3f122f10609
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -0,0 +1,9 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo<'a, 'b> = impl std::fmt::Debug;
+
+fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+    (i, i) //~ ERROR concrete type differs from previous
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
new file mode 100644
index 00000000000..81e603e2355
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -0,0 +1,11 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
+   |
+LL |     (i, i)
+   |     ^^^^^^
+   |     |
+   |     expected `&'a i32`, got `&'b i32`
+   |     this expression supplies two conflicting concrete types for the same opaque type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
index f412b2d0e7d..83fd9a1da45 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
@@ -7,6 +7,15 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>)
     (a.clone(), a)
 }
 
+type Foo<'a, 'b> = impl std::fmt::Debug;
+
+fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
+    (i, j)
+}
+
 fn main() {
     println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
+    let meh = 42;
+    let muh = 69;
+    println!("{:?}", foo(&meh, &muh));
 }
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
index da845e86147..46bac5a34f5 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -7,8 +7,8 @@
 type X<A, B> = impl Into<&'static A>;
 
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-    //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
     (a, a)
+    //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
 }
 
 fn main() {
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index 4df2f52a9e4..f4d8b4509d4 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
-  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
+  --> $DIR/multiple-def-uses-in-one-fn.rs:10:9
    |
-LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-   |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
+LL |     (a, a)
+   |         ^ the trait `From<&A>` is not implemented for `&'static B`
    |
    = note: required because of the requirements on the impl of `Into<&'static B>` for `&A`
 help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
index 06e1990fd7f..14510a5294e 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
@@ -7,8 +7,8 @@
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
 
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
-    //~^ ERROR concrete type differs from previous defining opaque type
     (a.clone(), a)
+    //~^ ERROR concrete type differs from previous defining opaque type
 }
 
 fn main() {
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
index 52b0462de98..0f752212ac9 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
@@ -1,14 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5
    |
-LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B`
-   |
-note: previous use here
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
-   |
-LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (a.clone(), a)
+   |     ^^^^^^^^^^^^^^
+   |     |
+   |     expected `A`, got `B`
+   |     this expression supplies two conflicting concrete types for the same opaque type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
index bbe709dccab..db4b60461ef 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
    |
+LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+   |                                                    ------------- the expected opaque type
+...
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
@@ -8,8 +11,8 @@ LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
-   = note: expected type parameter `A`
-              found type parameter `B`
+   = note: expected opaque type `X<A, B>`
+           found type parameter `B`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs
index efb88dabf34..314e5362a8f 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
@@ -12,6 +10,9 @@ trait Foo<A> { }
 impl Foo<()> for () { }
 
 fn foo() -> impl Foo<FooX> {
+    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
+    //~| ERROR: the trait bound `(): Foo<FooX>` is not satisfied
+    // FIXME(type-alias-impl-trait): We could probably make this work.
     ()
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr
new file mode 100644
index 00000000000..eb72e887691
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference.rs:12:13
+   |
+LL | fn foo() -> impl Foo<FooX> {
+   |             ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<()>>
+
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference.rs:12:28
+   |
+LL |   fn foo() -> impl Foo<FooX> {
+   |  ____________________________^
+LL | |
+LL | |
+LL | |     // FIXME(type-alias-impl-trait): We could probably make this work.
+LL | |     ()
+LL | | }
+   | |_^ the trait `Foo<FooX>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<()>>
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs
index 9b26a652978..4dc30d9257b 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs
@@ -4,7 +4,6 @@
 use std::fmt::Debug;
 
 type FooX = impl Debug;
-//~^ ERROR: could not find defining uses
 
 trait Foo<A> {}
 
@@ -12,7 +11,8 @@ impl Foo<()> for () {}
 impl Foo<u32> for () {}
 
 fn foo() -> impl Foo<FooX> {
-    //~^ ERROR: the trait bound `(): Foo<impl Debug>` is not satisfied [E0277]
+    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
+    //~| ERROR: the trait bound `(): Foo<FooX>` is not satisfied
     ()
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
index 7e24ee644b1..1372a018667 100644
--- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
@@ -1,18 +1,27 @@
-error[E0277]: the trait bound `(): Foo<impl Debug>` is not satisfied
-  --> $DIR/nested-tait-inference2.rs:14:13
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference2.rs:13:13
    |
 LL | fn foo() -> impl Foo<FooX> {
-   |             ^^^^^^^^^^^^^^ the trait `Foo<impl Debug>` is not implemented for `()`
+   |             ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
    |
    = help: the following implementations were found:
              <() as Foo<()>>
              <() as Foo<u32>>
 
-error: could not find defining uses
-  --> $DIR/nested-tait-inference2.rs:6:13
+error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
+  --> $DIR/nested-tait-inference2.rs:13:28
    |
-LL | type FooX = impl Debug;
-   |             ^^^^^^^^^^
+LL |   fn foo() -> impl Foo<FooX> {
+   |  ____________________________^
+LL | |
+LL | |
+LL | |     ()
+LL | | }
+   | |_^ the trait `Foo<FooX>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<()>>
+             <() as Foo<u32>>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
new file mode 100644
index 00000000000..fbab5470b4f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.rs
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+type FooX = impl Debug;
+//~^ unconstrained opaque type
+
+trait Foo<A> { }
+
+impl Foo<FooX> for () { }
+
+fn foo() -> impl Foo<FooX> {
+    ()
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
new file mode 100644
index 00000000000..b1d947a9ccf
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference3.stderr
@@ -0,0 +1,10 @@
+error: unconstrained opaque type
+  --> $DIR/nested-tait-inference3.rs:6:13
+   |
+LL | type FooX = impl Debug;
+   |             ^^^^^^^^^^
+   |
+   = note: `FooX` must be used in combination with a concrete type within the same module
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/nested.rs b/src/test/ui/type-alias-impl-trait/nested.rs
new file mode 100644
index 00000000000..6b866be7d17
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested.rs
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+type Bar = impl Trait<Foo>;
+
+trait Trait<T> {}
+
+impl<T, U> Trait<T> for U {}
+
+fn bar() -> Bar {
+    42
+}
+
+fn main() {
+    println!("{:?}", bar());
+    //~^ ERROR `Bar` doesn't implement `Debug`
+}
diff --git a/src/test/ui/type-alias-impl-trait/nested.stderr b/src/test/ui/type-alias-impl-trait/nested.stderr
new file mode 100644
index 00000000000..cf4d23656e0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested.stderr
@@ -0,0 +1,12 @@
+error[E0277]: `Bar` doesn't implement `Debug`
+  --> $DIR/nested.rs:15:22
+   |
+LL |     println!("{:?}", bar());
+   |                      ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `Bar`
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
index 6282264d8fe..60b6e1aac62 100644
--- a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
+++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
@@ -1,5 +1,5 @@
 #![feature(type_alias_impl_trait)]
-// build-pass (FIXME(62277): could be check-pass?)
+
 mod my_mod {
     use std::fmt::Debug;
 
@@ -11,7 +11,7 @@ mod my_mod {
     }
 
     pub fn get_foot() -> Foot {
-        get_foo()
+        get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
new file mode 100644
index 00000000000..fa6ecf68d28
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
@@ -0,0 +1,19 @@
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/nested_type_alias_impl_trait.rs:14:9
+   |
+LL |         get_foo()
+   |         ^^^^^^^^^ 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/nested_type_alias_impl_trait.rs:7:21
+   |
+LL |     pub type Foot = impl Debug;
+   |                     ^^^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/nested_type_alias_impl_trait.rs:6:20
+   |
+LL |     pub type Foo = impl Debug;
+   |                    ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
index 8787c023eb0..fed5ac07c90 100644
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
+++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
@@ -1,8 +1,7 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 fn main() {}
 
-// don't reveal the concrete type
 type NoReveal = impl std::fmt::Debug;
 
 fn define_no_reveal() -> NoReveal {
@@ -10,6 +9,6 @@ fn define_no_reveal() -> NoReveal {
 }
 
 fn no_reveal(x: NoReveal) {
-    let _: &'static str = x; //~ mismatched types
-    let _ = x as &'static str; //~ non-primitive cast
+    let _: &'static str = x;
+    let _ = x as &'static str;
 }
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
deleted file mode 100644
index b438f844516..00000000000
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/never_reveal_concrete_type.rs:13:27
-   |
-LL | type NoReveal = impl std::fmt::Debug;
-   |                 -------------------- the found opaque type
-...
-LL |     let _: &'static str = x;
-   |            ------------   ^ expected `&str`, found opaque type
-   |            |
-   |            expected due to this
-   |
-   = note: expected reference `&'static str`
-            found opaque type `impl Debug`
-
-error[E0605]: non-primitive cast: `impl Debug` as `&'static str`
-  --> $DIR/never_reveal_concrete_type.rs:14:13
-   |
-LL |     let _ = x as &'static str;
-   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0308, E0605.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
index 1197c7bc58e..fa578eced5f 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
@@ -1,9 +1,9 @@
 // Issue 52985: user code provides no use case that allows a type alias `impl Trait`
-// We now emit a 'could not find defining uses' error
+// We now emit a 'unconstrained opaque type' error
 
 #![feature(type_alias_impl_trait)]
 
-type Foo = impl Copy; //~ could not find defining uses
+type Foo = impl Copy; //~ unconstrained opaque type
 
 // make compiler happy about using 'Foo'
 fn bar(x: Foo) -> Foo {
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index 61025e84692..009935347e6 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/no_inferrable_concrete_type.rs:6:12
    |
 LL | type Foo = impl Copy;
    |            ^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index 67752acb8c9..ae03a5b3e37 100644
--- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -10,7 +10,7 @@ LL |     let _: &str = bomp();
    |            expected due to this
    |
    = note: expected reference `&str`
-            found opaque type `impl Debug`
+            found opaque type `Boo`
 
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
@@ -19,11 +19,11 @@ LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ---------------------- the expected opaque type
 ...
 LL | fn bomp() -> boo::Boo {
-   |              -------- expected `impl Debug` because of return type
+   |              -------- expected `Boo` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `impl Debug`
+   = note: expected opaque type `Boo`
                 found reference `&'static str`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
index 107cd394579..289784ce747 100644
--- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
+++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
@@ -7,11 +7,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 //~^ ERROR `T` doesn't implement `Debug`
 
-fn two<T: Debug>(t: T) -> Two<T, u32> {
-    //~^ ERROR non-defining opaque type use in defining scope
-    (t, 4i8)
-}
-
 fn three<T: Debug, U>(t: T) -> Two<T, U> {
     (t, 5i8)
 }
@@ -27,8 +22,8 @@ impl Bar for u32 {
 }
 
 fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
-    //~^ ERROR concrete type differs from previous
     (t, <U as Bar>::FOO)
+    //~^ ERROR concrete type differs from previous
 }
 
 fn is_sync<T: Sync>() {}
diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
index 08e49845521..6068cfeb51e 100644
--- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
@@ -1,26 +1,14 @@
-error: non-defining opaque type use in defining scope
-  --> $DIR/not_a_defining_use.rs:10:27
-   |
-LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
-   |                           ^^^^^^^^^^^
-   |
-note: used non-generic type `u32` for generic parameter
-  --> $DIR/not_a_defining_use.rs:7:13
-   |
-LL | type Two<T, U> = impl Debug;
-   |             ^
-
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/not_a_defining_use.rs:29:1
+  --> $DIR/not_a_defining_use.rs:25:5
    |
-LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+LL |     (t, <U as Bar>::FOO)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
-  --> $DIR/not_a_defining_use.rs:15:1
+  --> $DIR/not_a_defining_use.rs:11:5
    |
-LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (t, 5i8)
+   |     ^^^^^^^^
 
 error[E0277]: `T` doesn't implement `Debug`
   --> $DIR/not_a_defining_use.rs:7:18
@@ -34,6 +22,6 @@ help: consider restricting type parameter `T`
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
    |           +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.rs b/src/test/ui/type-alias-impl-trait/reveal_local.rs
new file mode 100644
index 00000000000..145186baa1f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.rs
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+//~^ ERROR cycle detected
+//~| ERROR cycle detected
+
+fn is_send<T: Send>() { }
+
+fn not_good() {
+    // Error: this function does not constrain `Foo` to any particular
+    // hidden type, so it cannot rely on `Send` being true.
+    is_send::<Foo>();
+}
+
+fn not_gooder() {
+    // Constrain `Foo = u32`
+    let x: Foo = 22_u32;
+
+    // while we could know this from the hidden type, it would
+    // need extra roundabout logic to support it.
+    is_send::<Foo>();
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.stderr b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
new file mode 100644
index 00000000000..5d48dd5b2bf
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
@@ -0,0 +1,51 @@
+error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
+  --> $DIR/reveal_local.rs:5:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+   |
+note: ...which requires type-checking `not_good`...
+  --> $DIR/reveal_local.rs:11:1
+   |
+LL | fn not_good() {
+   | ^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/reveal_local.rs:1:1
+   |
+LL | / #![feature(type_alias_impl_trait)]
+LL | |
+LL | | use std::fmt::Debug;
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
+  --> $DIR/reveal_local.rs:5:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+   |
+note: ...which requires type-checking `not_gooder`...
+  --> $DIR/reveal_local.rs:17:1
+   |
+LL | fn not_gooder() {
+   | ^^^^^^^^^^^^^^^
+   = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in top-level module
+  --> $DIR/reveal_local.rs:1:1
+   |
+LL | / #![feature(type_alias_impl_trait)]
+LL | |
+LL | | use std::fmt::Debug;
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.rs b/src/test/ui/type-alias-impl-trait/self-referential-2.rs
new file mode 100644
index 00000000000..dc7054da5ec
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential-2.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl std::fmt::Debug;
+type Bar = impl PartialEq<Foo>;
+
+fn bar() -> Bar {
+    42_i32 //~ ERROR can't compare `i32` with `Foo`
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
new file mode 100644
index 00000000000..6997676260d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
@@ -0,0 +1,11 @@
+error[E0277]: can't compare `i32` with `Foo`
+  --> $DIR/self-referential-2.rs:7:5
+   |
+LL |     42_i32
+   |     ^^^^^^ no implementation for `i32 == Foo`
+   |
+   = help: the trait `PartialEq<Foo>` is not implemented for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-3.rs b/src/test/ui/type-alias-impl-trait/self-referential-3.rs
new file mode 100644
index 00000000000..d40715717d4
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential-3.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 42;
+    assert_eq!(bar(&meh), bar(&muh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.rs b/src/test/ui/type-alias-impl-trait/self-referential-4.rs
new file mode 100644
index 00000000000..697ec56825a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential-4.rs
@@ -0,0 +1,25 @@
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'static>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Bar<'b, 'static>`
+}
+
+type Foo<'a, 'b> = impl PartialEq<Foo<'static, 'b>> + std::fmt::Debug;
+
+fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Foo<'static, 'b>`
+}
+
+type Moo<'a, 'b> = impl PartialEq<Moo<'static, 'a>> + std::fmt::Debug;
+
+fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Moo<'static, 'a>`
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 69;
+    assert_eq!(bar(&meh), bar(&meh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
new file mode 100644
index 00000000000..4a6ee2f9279
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
@@ -0,0 +1,27 @@
+error[E0277]: can't compare `&i32` with `Bar<'b, 'static>`
+  --> $DIR/self-referential-4.rs:6:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Bar<'b, 'static>`
+   |
+   = help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `Foo<'static, 'b>`
+  --> $DIR/self-referential-4.rs:12:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Foo<'static, 'b>`
+   |
+   = help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `Moo<'static, 'a>`
+  --> $DIR/self-referential-4.rs:18:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Moo<'static, 'a>`
+   |
+   = help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.rs b/src/test/ui/type-alias-impl-trait/self-referential.rs
new file mode 100644
index 00000000000..4974ac72dad
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential.rs
@@ -0,0 +1,25 @@
+#![feature(type_alias_impl_trait)]
+
+type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'a>> + std::fmt::Debug;
+
+fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    i //~ ERROR can't compare `&i32` with `Bar<'b, 'a>`
+}
+
+type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
+
+fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
+    (42, i) //~ ERROR can't compare `&i32` with `(i32, &i32)`
+}
+
+type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
+
+fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
+    (42, i) //~ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+}
+
+fn main() {
+    let meh = 42;
+    let muh = 69;
+    assert_eq!(bar(&meh), bar(&meh));
+}
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr
new file mode 100644
index 00000000000..0626e6be0d5
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr
@@ -0,0 +1,27 @@
+error[E0277]: can't compare `&i32` with `Bar<'b, 'a>`
+  --> $DIR/self-referential.rs:6:5
+   |
+LL |     i
+   |     ^ no implementation for `&i32 == Bar<'b, 'a>`
+   |
+   = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `(i32, &i32)`
+  --> $DIR/self-referential.rs:12:10
+   |
+LL |     (42, i)
+   |          ^ no implementation for `&i32 == (i32, &i32)`
+   |
+   = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32`
+
+error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+  --> $DIR/self-referential.rs:18:10
+   |
+LL |     (42, i)
+   |          ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})`
+   |
+   = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs
index 86b685022b2..748a279e439 100644
--- a/src/test/ui/type-alias-impl-trait/static-const-types.rs
+++ b/src/test/ui/type-alias-impl-trait/static-const-types.rs
@@ -1,13 +1,13 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME: This should compile, but it currently doesn't
+// check-pass
 
 use std::fmt::Debug;
 
-type Foo = impl Debug; //~ ERROR could not find defining uses
+type Foo = impl Debug;
 
-static FOO1: Foo = 22_u32; //~ ERROR mismatched types
-const FOO2: Foo = 22_u32; //~ ERROR mismatched types
+static FOO1: Foo = 22_u32;
+const FOO2: Foo = 22_u32;
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr
deleted file mode 100644
index 6f4c2944f72..00000000000
--- a/src/test/ui/type-alias-impl-trait/static-const-types.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:10:20
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-LL | 
-LL | static FOO1: Foo = 22_u32;
-   |                    ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/static-const-types.rs:11:19
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL | const FOO2: Foo = 22_u32;
-   |                   ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error: could not find defining uses
-  --> $DIR/static-const-types.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
index 219837aa04b..c2ab6a9d10a 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
+++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
@@ -10,9 +10,9 @@ const fn leak_free() -> Bar {
 const LEAK_FREE: Bar = leak_free();
 
 fn leak_free_test() {
-    match todo!() {
+    match LEAK_FREE {
         LEAK_FREE => (),
-        //~^ `impl Send` cannot be used in patterns
+        //~^ `Bar` cannot be used in patterns
         _ => (),
     }
 }
diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
index 889c4fd4b04..dbc183f54f4 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
+++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
@@ -1,4 +1,4 @@
-error: `impl Send` cannot be used in patterns
+error: `Bar` cannot be used in patterns
   --> $DIR/structural-match-no-leak.rs:14:9
    |
 LL |         LEAK_FREE => (),
diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs
index c9e669cad60..7cc9ccaabdc 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match.rs
+++ b/src/test/ui/type-alias-impl-trait/structural-match.rs
@@ -11,9 +11,9 @@ const fn value() -> Foo {
 const VALUE: Foo = value();
 
 fn test() {
-    match todo!() {
+    match VALUE {
         VALUE => (),
-        //~^ `impl Send` cannot be used in patterns
+        //~^ `Foo` cannot be used in patterns
         _ => (),
     }
 }
diff --git a/src/test/ui/type-alias-impl-trait/structural-match.stderr b/src/test/ui/type-alias-impl-trait/structural-match.stderr
index 262fd072613..61287f26806 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match.stderr
+++ b/src/test/ui/type-alias-impl-trait/structural-match.stderr
@@ -1,4 +1,4 @@
-error: `impl Send` cannot be used in patterns
+error: `Foo` cannot be used in patterns
   --> $DIR/structural-match.rs:15:9
    |
 LL |         VALUE => (),
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
index 1a8113848f9..5630e036be3 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
@@ -1,13 +1,11 @@
 #![feature(type_alias_impl_trait)]
-
+// check-pass
 // Ensures that `const` items can constrain an opaque `impl Trait`.
 
 use std::fmt::Debug;
 
 pub type Foo = impl Debug;
-//~^ ERROR could not find defining uses
 
 const _FOO: Foo = 5;
-//~^ ERROR mismatched types [E0308]
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
deleted file mode 100644
index e2567e87ac6..00000000000
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/type-alias-impl-trait-const.rs:10:19
-   |
-LL | pub type Foo = impl Debug;
-   |                ---------- the expected opaque type
-...
-LL | const _FOO: Foo = 5;
-   |                   ^ expected opaque type, found integer
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `{integer}`
-
-error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-const.rs:7:16
-   |
-LL | pub type Foo = impl Debug;
-   |                ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs
index c009952eab7..e5e7fb677ed 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs
@@ -1,7 +1,7 @@
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Fn() -> Foo;
-//~^ ERROR: could not find defining uses
+//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
index 726f4ea6e00..a770eeac39b 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12
    |
 LL | type Foo = impl Fn() -> Foo;
    |            ^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs
index f3898bca64b..7c7a1b405bc 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs
@@ -5,7 +5,7 @@ pub trait Bar<T> {
 }
 
 type Foo = impl Bar<Foo, Item = Foo>;
-//~^ ERROR: could not find defining uses
+//~^ ERROR: unconstrained opaque type
 
 fn crash(x: Foo) -> Foo {
     x
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
index 3947cc4d270..3f3699ce532 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
@@ -1,8 +1,10 @@
-error: could not find defining uses
+error: unconstrained opaque type
   --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12
    |
 LL | type Foo = impl Bar<Foo, Item = Foo>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same module
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs
index d2c8c1f63df..70c2ee4278c 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 #![allow(dead_code)]
 #![allow(unused_assignments)]
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
new file mode 100644
index 00000000000..67f56bcde93
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
@@ -0,0 +1,84 @@
+// check-pass
+
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![feature(type_alias_impl_trait)]
+
+fn main() {
+    assert_eq!(foo().to_string(), "foo");
+    assert_eq!(bar1().to_string(), "bar1");
+    assert_eq!(bar2().to_string(), "bar2");
+    let mut x = bar1();
+    x = bar2();
+    assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]);
+}
+
+use defining_use_scope::*;
+
+mod defining_use_scope {
+    // single definition
+    pub type Foo = impl std::fmt::Display;
+
+    pub fn foo() -> Foo {
+        "foo"
+    }
+
+    // two definitions
+    pub type Bar = impl std::fmt::Display;
+
+    pub fn bar1() -> Bar {
+        "bar1"
+    }
+
+    pub fn bar2() -> Bar {
+        "bar2"
+    }
+
+    pub type MyIter<T> = impl Iterator<Item = T>;
+
+    pub fn my_iter<T>(t: T) -> MyIter<T> {
+        std::iter::once(t)
+    }
+
+    fn my_iter2<T>(t: T) -> MyIter<T> {
+        std::iter::once(t)
+    }
+
+    // param names should not have an effect!
+    fn my_iter3<U>(u: U) -> MyIter<U> {
+        std::iter::once(u)
+    }
+
+    // param position should not have an effect!
+    fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
+        std::iter::once(v)
+    }
+
+    // param names should not have an effect!
+    type MyOtherIter<T> = impl Iterator<Item = T>;
+
+    fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
+        std::iter::once(u)
+    }
+
+    trait Trait {}
+    type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
+
+    fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
+        t
+    }
+
+    mod pass_through {
+        pub type Passthrough<T: 'static> = impl Sized + 'static;
+
+        fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
+            t
+        }
+    }
+
+    fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> {
+        x
+    }
+
+}
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
index 7f8e6127cca..4e9d1788b94 100644
--- a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -1,27 +1,20 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME This should compile, but it currently doesn't
-
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR: could not find defining uses
 
 fn foo1() -> u32 {
     let x: Foo = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
     x
-    //~^ ERROR: mismatched types [E0308]
 }
 
 fn foo2() -> u32 {
     let x: Foo = 22_u32;
-    //~^ ERROR: mismatched types [E0308]
     let y: Foo = x;
-    same_type((x, y));
-    y
-    //~^ ERROR: mismatched types [E0308]
+    same_type((x, y)); //~ ERROR use of moved value
+    y //~ ERROR use of moved value
 }
 
 fn same_type<T>(x: (T, T)) {}
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
index cac8d6841af..1dabe4586c5 100644
--- a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
@@ -1,67 +1,23 @@
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:12:18
+error[E0382]: use of moved value: `x`
+  --> $DIR/type_of_a_let.rs:16:16
    |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
 LL |     let x: Foo = 22_u32;
-   |            ---   ^^^^^^ expected opaque type, found `u32`
-   |            |
-   |            expected due to this
-   |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:14:5
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the found opaque type
-...
-LL | fn foo1() -> u32 {
-   |              --- expected `u32` because of return type
-...
-LL |     x
-   |     ^ expected `u32`, found opaque type
-   |
-   = note:     expected type `u32`
-           found opaque type `impl Debug`
+   |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
+LL |     let y: Foo = x;
+   |                  - value moved here
+LL |     same_type((x, y));
+   |                ^ value used here after move
 
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:19:18
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the expected opaque type
-...
-LL |     let x: Foo = 22_u32;
-   |            ---   ^^^^^^ expected opaque type, found `u32`
-   |            |
-   |            expected due to this
+error[E0382]: use of moved value: `y`
+  --> $DIR/type_of_a_let.rs:17:5
    |
-   = note: expected opaque type `impl Debug`
-                     found type `u32`
-
-error[E0308]: mismatched types
-  --> $DIR/type_of_a_let.rs:23:5
-   |
-LL | type Foo = impl Debug;
-   |            ---------- the found opaque type
-...
-LL | fn foo2() -> u32 {
-   |              --- expected `u32` because of return type
-...
+LL |     let y: Foo = x;
+   |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
+LL |     same_type((x, y));
+   |                   - value moved here
 LL |     y
-   |     ^ expected `u32`, found opaque type
-   |
-   = note:     expected type `u32`
-           found opaque type `impl Debug`
-
-error: could not find defining uses
-  --> $DIR/type_of_a_let.rs:8:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
+   |     ^ value used here after move
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0382`.