about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-06-15 04:10:24 +0000
committerbors <bors@rust-lang.org>2020-06-15 04:10:24 +0000
commitce6d3a73b514e9649e57cee812ad129bb2112016 (patch)
tree39b78deb20d2b50a0eaec85d605bb015e6cfa35a
parent4fb54ed484e2239a3e9eff3be17df00d2a162be3 (diff)
parent8b10d42ebe7843bcaed58dcbbc8836a0f27b54c9 (diff)
downloadrust-ce6d3a73b514e9649e57cee812ad129bb2112016.tar.gz
rust-ce6d3a73b514e9649e57cee812ad129bb2112016.zip
Auto merge of #72080 - matthewjasper:uniform-impl-trait, r=nikomatsakis
Clean up type alias impl trait implementation

- Removes special case for top-level impl trait
- Removes associated opaque types
- Forbid lifetime elision in let position impl trait. This is consistent with the behavior for inferred types.
- Handle lifetimes in type alias impl trait more uniformly with other parameters

cc #69323
cc #63063
Closes #57188
Closes #62988
Closes #69136
Closes #73061
-rw-r--r--src/librustc_ast/ast.rs9
-rw-r--r--src/librustc_ast_lowering/item.rs80
-rw-r--r--src/librustc_ast_lowering/lib.rs148
-rw-r--r--src/librustc_hir/def.rs8
-rw-r--r--src/librustc_hir/hir.rs21
-rw-r--r--src/librustc_hir/intravisit.rs6
-rw-r--r--src/librustc_hir_pretty/lib.rs8
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs1
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs3
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs2
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs7
-rw-r--r--src/librustc_metadata/rmeta/mod.rs1
-rw-r--r--src/librustc_middle/hir/map/mod.rs12
-rw-r--r--src/librustc_middle/traits/specialization_graph.rs17
-rw-r--r--src/librustc_middle/ty/error.rs4
-rw-r--r--src/librustc_middle/ty/mod.rs20
-rw-r--r--src/librustc_mir/borrow_check/type_check/free_region_relations.rs8
-rw-r--r--src/librustc_passes/check_attr.rs2
-rw-r--r--src/librustc_passes/dead.rs4
-rw-r--r--src/librustc_passes/layout_test.rs7
-rw-r--r--src/librustc_passes/reachable.rs4
-rw-r--r--src/librustc_privacy/lib.rs14
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs14
-rw-r--r--src/librustc_resolve/late/lifetimes.rs79
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs3
-rw-r--r--src/librustc_save_analysis/lib.rs1
-rw-r--r--src/librustc_save_analysis/sig.rs2
-rw-r--r--src/librustc_trait_selection/opaque_types.rs96
-rw-r--r--src/librustc_trait_selection/traits/project.rs11
-rw-r--r--src/librustc_ty/ty.rs2
-rw-r--r--src/librustc_typeck/astconv.rs27
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/compare_method.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs5
-rw-r--r--src/librustc_typeck/check/wfcheck.rs191
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/librustc_typeck/collect.rs51
-rw-r--r--src/librustc_typeck/collect/type_of.rs91
-rw-r--r--src/librustc_typeck/impl_wf_check.rs7
-rw-r--r--src/librustdoc/clean/mod.rs7
-rw-r--r--src/test/rustdoc/auxiliary/issue-73061.rs17
-rw-r--r--src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs14
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.rs6
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.stderr198
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs24
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr70
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs14
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.stderr4
-rw-r--r--src/test/ui/impl-trait/issue-60473.rs10
-rw-r--r--src/test/ui/impl-trait/issue-60473.stderr16
-rw-r--r--src/test/ui/impl-trait/issue-67166.rs4
-rw-r--r--src/test/ui/impl-trait/issue-67166.stderr16
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs15
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr10
-rw-r--r--src/test/ui/impl-trait/where-allowed.stderr12
-rw-r--r--src/test/ui/issues/issue-60662.stdout2
-rw-r--r--src/test/ui/lint/inline-trait-and-foreign-items.stderr4
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.rs3
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.stderr6
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.rs9
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.stderr25
-rw-r--r--src/test/ui/save-analysis/issue-68621.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.stderr4
-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.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs24
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60371.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs38
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs22
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs23
-rw-r--r--src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr6
-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.stderr10
-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.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/hir_utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs1
99 files changed, 923 insertions, 851 deletions
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index d3e3546cf31..62406552e31 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -1860,15 +1860,6 @@ impl TyKind {
     pub fn is_unit(&self) -> bool {
         if let TyKind::Tup(ref tys) = *self { tys.is_empty() } else { false }
     }
-
-    /// HACK(type_alias_impl_trait, Centril): A temporary crutch used
-    /// in lowering to avoid making larger changes there and beyond.
-    pub fn opaque_top_hack(&self) -> Option<&GenericBounds> {
-        match self {
-            Self::ImplTrait(_, bounds) => Some(bounds),
-            _ => None,
-        }
-    }
 }
 
 /// Syntax used to declare a trait object.
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 47d10f86d03..8cfbd408e22 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -1,5 +1,5 @@
 use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
-use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor};
+use super::{ImplTraitContext, ImplTraitPosition};
 use crate::Arena;
 
 use rustc_ast::ast::*;
@@ -7,6 +7,7 @@ use rustc_ast::attr;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -165,13 +166,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ItemKind::MacroDef(..) => SmallVec::new(),
             ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id],
-            ItemKind::Static(ref ty, ..) | ItemKind::Const(_, ref ty, ..) => {
-                let mut ids = smallvec![i.id];
-                if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitTypeIdVisitor { ids: &mut ids }.visit_ty(ty);
-                }
-                ids
-            }
             _ => smallvec![i.id],
         };
 
@@ -292,23 +286,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
-                None => {
-                    let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
-                    let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
-                    hir::ItemKind::TyAlias(ty, generics)
-                }
-                Some(bounds) => {
-                    let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
-                    let ty = hir::OpaqueTy {
-                        generics: self.lower_generics(gen, ctx()),
-                        bounds: self.lower_param_bounds(bounds, ctx()),
-                        impl_trait_fn: None,
-                        origin: hir::OpaqueTyOrigin::TypeAlias,
-                    };
-                    hir::ItemKind::OpaqueTy(ty)
-                }
-            },
+            ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
+                // We lower
+                //
+                // type Foo = impl Trait
+                //
+                // to
+                //
+                // type Foo = Foo1
+                // opaque type Foo1: Trait
+                let ty = self.lower_ty(
+                    ty,
+                    ImplTraitContext::OtherOpaqueTy {
+                        capturable_lifetimes: &mut FxHashSet::default(),
+                        origin: hir::OpaqueTyOrigin::Misc,
+                    },
+                );
+                let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
+                hir::ItemKind::TyAlias(ty, generics)
+            }
             ItemKind::TyAlias(_, ref generics, _, None) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
@@ -438,8 +434,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         body: Option<&Expr>,
     ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
+        let mut capturable_lifetimes;
         let itctx = if self.sess.features_untracked().impl_trait_in_bindings {
-            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
+            capturable_lifetimes = FxHashSet::default();
+            ImplTraitContext::OtherOpaqueTy {
+                capturable_lifetimes: &mut capturable_lifetimes,
+                origin: hir::OpaqueTyOrigin::Misc,
+            }
         } else {
             ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
         };
@@ -844,16 +845,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err));
                         hir::ImplItemKind::TyAlias(ty)
                     }
-                    Some(ty) => match ty.kind.opaque_top_hack() {
-                        None => {
-                            let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
-                            hir::ImplItemKind::TyAlias(ty)
-                        }
-                        Some(bs) => {
-                            let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
-                            hir::ImplItemKind::OpaqueTy(bs)
-                        }
-                    },
+                    Some(ty) => {
+                        let ty = self.lower_ty(
+                            ty,
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut FxHashSet::default(),
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
+                        );
+                        hir::ImplItemKind::TyAlias(ty)
+                    }
                 };
                 (generics, kind)
             }
@@ -887,12 +888,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             defaultness,
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
-                AssocItemKind::TyAlias(.., ty) => {
-                    match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
-                        None => hir::AssocItemKind::Type,
-                        Some(_) => hir::AssocItemKind::OpaqueTy,
-                    }
-                }
+                AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
                 AssocItemKind::Fn(_, sig, ..) => {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 1f8c68f75e9..d7946ad0094 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -224,11 +224,30 @@ enum ImplTraitContext<'b, 'a> {
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
     /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
     ///
-    /// We optionally store a `DefId` for the parent item here so we can look up necessary
-    /// information later. It is `None` when no information about the context should be stored
-    /// (e.g., for consts and statics).
-    OpaqueTy(Option<DefId> /* fn def-ID */, hir::OpaqueTyOrigin),
-
+    ReturnPositionOpaqueTy {
+        /// `DefId` for the parent function, used to look up necessary
+        /// information later.
+        fn_def_id: DefId,
+        /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
+        origin: hir::OpaqueTyOrigin,
+    },
+    /// Impl trait in type aliases, consts and statics.
+    OtherOpaqueTy {
+        /// Set of lifetimes that this opaque type can capture, if it uses
+        /// them. This includes lifetimes bound since we entered this context.
+        /// For example, in
+        ///
+        /// type A<'b> = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
+        ///
+        /// the inner opaque type captures `'a` because it uses it. It doesn't
+        /// need to capture `'b` because it already inherits the lifetime
+        /// parameter from `A`.
+        // FIXME(impl_trait): but `required_region_bounds` will ICE later
+        // anyway.
+        capturable_lifetimes: &'b mut FxHashSet<hir::LifetimeName>,
+        /// Origin: Either OpaqueTyOrigin::Misc or OpaqueTyOrigin::Binding,
+        origin: hir::OpaqueTyOrigin,
+    },
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
 }
@@ -253,7 +272,12 @@ impl<'a> ImplTraitContext<'_, 'a> {
         use self::ImplTraitContext::*;
         match self {
             Universal(params) => Universal(params),
-            OpaqueTy(fn_def_id, origin) => OpaqueTy(*fn_def_id, *origin),
+            ReturnPositionOpaqueTy { fn_def_id, origin } => {
+                ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin }
+            }
+            OtherOpaqueTy { capturable_lifetimes, origin } => {
+                OtherOpaqueTy { capturable_lifetimes, origin: *origin }
+            }
             Disallowed(pos) => Disallowed(*pos),
         }
     }
@@ -1001,6 +1025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
             }
             AssocTyConstraintKind::Bound { ref bounds } => {
+                let mut capturable_lifetimes;
                 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
                 let (desugar_to_impl_trait, itctx) = match itctx {
                     // We are in the return position:
@@ -1010,7 +1035,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // so desugar to
                     //
                     //     fn foo() -> impl Iterator<Item = impl Debug>
-                    ImplTraitContext::OpaqueTy(..) => (true, itctx),
+                    ImplTraitContext::ReturnPositionOpaqueTy { .. }
+                    | ImplTraitContext::OtherOpaqueTy { .. } => (true, itctx),
 
                     // We are in the argument position, but within a dyn type:
                     //
@@ -1028,7 +1054,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     //
                     // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
                     ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
-                        (true, ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc))
+                        capturable_lifetimes = FxHashSet::default();
+                        (
+                            true,
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut capturable_lifetimes,
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
+                        )
                     }
 
                     // We are in the parameter position, but not within a dyn type:
@@ -1270,10 +1303,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             TyKind::ImplTrait(def_node_id, ref bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::OpaqueTy(fn_def_id, origin) => {
-                        self.lower_opaque_impl_trait(span, fn_def_id, origin, def_node_id, |this| {
-                            this.lower_param_bounds(bounds, itctx)
-                        })
+                    ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, origin } => self
+                        .lower_opaque_impl_trait(
+                            span,
+                            Some(fn_def_id),
+                            origin,
+                            def_node_id,
+                            None,
+                            |this| this.lower_param_bounds(bounds, itctx),
+                        ),
+                    ImplTraitContext::OtherOpaqueTy { ref capturable_lifetimes, origin } => {
+                        // Reset capturable lifetimes, any nested impl trait
+                        // types will inherit lifetimes from this opaque type,
+                        // so don't need to capture them again.
+                        let nested_itctx = ImplTraitContext::OtherOpaqueTy {
+                            capturable_lifetimes: &mut FxHashSet::default(),
+                            origin,
+                        };
+                        self.lower_opaque_impl_trait(
+                            span,
+                            None,
+                            origin,
+                            def_node_id,
+                            Some(capturable_lifetimes),
+                            |this| this.lower_param_bounds(bounds, nested_itctx),
+                        )
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         // Add a definition for the in-band `Param`.
@@ -1351,6 +1405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         fn_def_id: Option<DefId>,
         origin: hir::OpaqueTyOrigin,
         opaque_ty_node_id: NodeId,
+        capturable_lifetimes: Option<&FxHashSet<hir::LifetimeName>>,
         lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
     ) -> hir::TyKind<'hir> {
         debug!(
@@ -1371,12 +1426,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
 
-        let (lifetimes, lifetime_defs) =
-            self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds);
+        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
+            opaque_ty_node_id,
+            opaque_ty_def_id,
+            &hir_bounds,
+            capturable_lifetimes,
+        );
 
-        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,);
+        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
 
-        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs,);
+        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
 
         self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
             let opaque_ty_item = hir::OpaqueTy {
@@ -1395,7 +1454,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-            hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, lifetimes)
+            hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, lifetimes)
         })
     }
 
@@ -1433,6 +1492,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         opaque_ty_id: NodeId,
         parent_def_id: LocalDefId,
         bounds: hir::GenericBounds<'hir>,
+        lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
     ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
         debug!(
             "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
@@ -1453,6 +1513,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
             output_lifetimes: Vec<hir::GenericArg<'hir>>,
             output_lifetime_params: Vec<hir::GenericParam<'hir>>,
+            lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
         }
 
         impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
@@ -1538,6 +1599,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 if !self.currently_bound_lifetimes.contains(&name)
                     && !self.already_defined_lifetimes.contains(&name)
+                    && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
                 {
                     self.already_defined_lifetimes.insert(name);
 
@@ -1591,6 +1653,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             already_defined_lifetimes: FxHashSet::default(),
             output_lifetimes: Vec::new(),
             output_lifetime_params: Vec::new(),
+            lifetimes_to_include,
         };
 
         for bound in bounds {
@@ -1614,15 +1677,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 visitor.visit_ty(ty);
             }
         }
-        let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
         let ty = l.ty.as_ref().map(|t| {
+            let mut capturable_lifetimes;
             self.lower_ty(
                 t,
                 if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitContext::OpaqueTy(
-                        Some(parent_def_id.to_def_id()),
-                        hir::OpaqueTyOrigin::Misc,
-                    )
+                    capturable_lifetimes = FxHashSet::default();
+                    ImplTraitContext::OtherOpaqueTy {
+                        capturable_lifetimes: &mut capturable_lifetimes,
+                        origin: hir::OpaqueTyOrigin::Binding,
+                    }
                 } else {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
                 },
@@ -1725,7 +1789,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 FnRetTy::Ty(ref ty) => {
                     let context = match in_band_ty_params {
                         Some((def_id, _)) if impl_trait_return_allow => {
-                            ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn)
+                            ImplTraitContext::ReturnPositionOpaqueTy {
+                                fn_def_id: def_id,
+                                origin: hir::OpaqueTyOrigin::FnReturn,
+                            }
                         }
                         _ => ImplTraitContext::disallowed(),
                     };
@@ -1944,7 +2011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
-        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args);
+        let opaque_ty_ref = hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, generic_args);
         let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
         hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
     }
@@ -1962,8 +2029,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
                 // `impl Future` opaque type that `async fn` implicitly
                 // generates.
-                let context =
-                    ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn);
+                let context = ImplTraitContext::ReturnPositionOpaqueTy {
+                    fn_def_id,
+                    origin: hir::OpaqueTyOrigin::FnReturn,
+                };
                 self.lower_ty(ty, context)
             }
             FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
@@ -2113,7 +2182,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(
                             x,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut FxHashSet::default(),
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
                         )
                     }),
                     synthetic: param
@@ -2169,8 +2241,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             &NodeMap::default(),
             itctx.reborrow(),
         );
+
         let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
-            this.lower_trait_ref(&p.trait_ref, itctx)
+            // Any impl Trait types defined within this scope can capture
+            // lifetimes bound on this predicate.
+            let lt_def_names = p.bound_generic_params.iter().filter_map(|param| match param.kind {
+                GenericParamKind::Lifetime { .. } => Some(hir::LifetimeName::Param(
+                    ParamName::Plain(param.ident.normalize_to_macros_2_0()),
+                )),
+                _ => None,
+            });
+            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+                capturable_lifetimes.extend(lt_def_names.clone());
+            }
+
+            let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
+
+            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+                for param in lt_def_names {
+                    capturable_lifetimes.remove(&param);
+                }
+            }
+            res
         });
 
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs
index 88049f85f45..af1860ca6bf 100644
--- a/src/librustc_hir/def.rs
+++ b/src/librustc_hir/def.rs
@@ -54,15 +54,11 @@ pub enum DefKind {
     /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
     Variant,
     Trait,
-    /// `type Foo = impl Bar;`
-    OpaqueTy,
     /// `type Foo = Bar;`
     TyAlias,
     ForeignTy,
     TraitAlias,
     AssocTy,
-    /// `type Foo = impl Bar;`
-    AssocOpaqueTy,
     TyParam,
 
     // Value namespace
@@ -83,6 +79,7 @@ pub enum DefKind {
     Use,
     ForeignMod,
     AnonConst,
+    OpaqueTy,
     Field,
     LifetimeParam,
     GlobalAsm,
@@ -115,7 +112,6 @@ impl DefKind {
             DefKind::TyAlias => "type alias",
             DefKind::TraitAlias => "trait alias",
             DefKind::AssocTy => "associated type",
-            DefKind::AssocOpaqueTy => "associated opaque type",
             DefKind::Union => "union",
             DefKind::Trait => "trait",
             DefKind::ForeignTy => "foreign type",
@@ -143,7 +139,6 @@ impl DefKind {
         match *self {
             DefKind::AssocTy
             | DefKind::AssocConst
-            | DefKind::AssocOpaqueTy
             | DefKind::AssocFn
             | DefKind::Enum
             | DefKind::OpaqueTy
@@ -168,7 +163,6 @@ impl DefKind {
             | DefKind::ForeignTy
             | DefKind::TraitAlias
             | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
             | DefKind::TyParam => ns == Namespace::TypeNS,
 
             DefKind::Fn
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 6b751456618..634ab32a285 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1921,14 +1921,12 @@ pub enum ImplItemKind<'hir> {
     Fn(FnSig<'hir>, BodyId),
     /// An associated type.
     TyAlias(&'hir Ty<'hir>),
-    /// An associated `type = impl Trait`.
-    OpaqueTy(GenericBounds<'hir>),
 }
 
 impl ImplItemKind<'_> {
     pub fn namespace(&self) -> Namespace {
         match self {
-            ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS,
+            ImplItemKind::TyAlias(..) => Namespace::TypeNS,
             ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
         }
     }
@@ -2018,13 +2016,13 @@ pub struct OpaqueTy<'hir> {
 /// From whence the opaque type came.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum OpaqueTyOrigin {
-    /// `type Foo = impl Trait;`
-    TypeAlias,
     /// `-> impl Trait`
     FnReturn,
     /// `async fn`
     AsyncFn,
-    /// Impl trait in bindings, consts, statics, bounds.
+    /// `let _: impl Trait = ...`
+    Binding,
+    /// Impl trait in type aliases, consts, statics, bounds.
     Misc,
 }
 
@@ -2050,12 +2048,12 @@ pub enum TyKind<'hir> {
     ///
     /// Type parameters may be stored in each `PathSegment`.
     Path(QPath<'hir>),
-    /// A type definition itself. This is currently only used for the `type Foo = impl Trait`
-    /// item that `impl Trait` in return position desugars to.
+    /// A opaque type definition itself. This is currently only used for the
+    /// `opaque type Foo: Trait` item that `impl Trait` in desugars to.
     ///
-    /// The generic argument list contains the lifetimes (and in the future possibly parameters)
-    /// that are actually bound on the `impl Trait`.
-    Def(ItemId, &'hir [GenericArg<'hir>]),
+    /// The generic argument list contains the lifetimes (and in the future
+    /// possibly parameters) that are actually bound on the `impl Trait`.
+    OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime),
@@ -2616,7 +2614,6 @@ pub enum AssocItemKind {
     Const,
     Fn { has_self: bool },
     Type,
-    OpaqueTy,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 6bc899622a3..23d642731da 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -690,7 +690,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
         TyKind::Path(ref qpath) => {
             visitor.visit_qpath(qpath, typ.hir_id, typ.span);
         }
-        TyKind::Def(item_id, lifetimes) => {
+        TyKind::OpaqueDef(item_id, lifetimes) => {
             visitor.visit_nested_item(item_id);
             walk_list!(visitor, visit_generic_arg, lifetimes);
         }
@@ -1007,10 +1007,6 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
             visitor.visit_id(impl_item.hir_id);
             visitor.visit_ty(ty);
         }
-        ImplItemKind::OpaqueTy(bounds) => {
-            visitor.visit_id(impl_item.hir_id);
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
     }
 }
 
diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs
index bf5b7152f0e..c16b7c63e31 100644
--- a/src/librustc_hir_pretty/lib.rs
+++ b/src/librustc_hir_pretty/lib.rs
@@ -407,7 +407,7 @@ impl<'a> State<'a> {
                     &f.param_names[..],
                 );
             }
-            hir::TyKind::Def(..) => {}
+            hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"),
             hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
             hir::TyKind::TraitObject(bounds, ref lifetime) => {
                 let mut first = true;
@@ -1003,12 +1003,6 @@ impl<'a> State<'a> {
             hir::ImplItemKind::TyAlias(ref ty) => {
                 self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
             }
-            hir::ImplItemKind::OpaqueTy(bounds) => {
-                self.word_space("type");
-                self.print_ident(ii.ident);
-                self.print_bounds("= impl", bounds);
-                self.s.word(";");
-            }
         }
         self.ann.post(self, AnnNode::SubItem(ii.hir_id))
     }
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 9bf992537df..2ee95174dff 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -336,7 +336,6 @@ impl DirtyCleanVisitor<'tcx> {
                 ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                 ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                 ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
-                ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
             },
             _ => self.tcx.sess.span_fatal(
                 attr.span,
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index a59a91e3005..12f7a9c0ca5 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -224,9 +224,7 @@ fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
 fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
     match item.kind {
         hir::ImplItemKind::Fn(..) => "method body",
-        hir::ImplItemKind::Const(..)
-        | hir::ImplItemKind::OpaqueTy(..)
-        | hir::ImplItemKind::TyAlias(..) => "associated item",
+        hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(..) => "associated item",
     }
 }
 
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index acaf4746992..a56401ebb90 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -84,7 +84,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 rustc_hir::intravisit::walk_ty(&mut v, ty);
 
                 debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
-                if sub == &ty::ReStatic && (matches!(ty.kind, TyKind::Def(_, _)) || v.0.len() == 1)
+                if sub == &ty::ReStatic
+                    && (matches!(ty.kind, TyKind::OpaqueDef(_, _)) || v.0.len() == 1)
                 {
                     debug!("try_report_named_anon_conflict: impl Trait + 'static");
                     // This is an `impl Trait` or `dyn Trait` return that evaluates de need of
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index aa0dd9c8311..efe60ce1b88 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1102,6 +1102,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
             hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics),
             _ => return,
         };
+        if let hir::TyKind::OpaqueDef(..) = ty.kind {
+            // Bounds are respected for `type X = impl Trait`
+            return;
+        }
         let mut suggested_changing_assoc_types = false;
         // There must not be a where clause
         if !type_alias_generics.where_clause.predicates.is_empty() {
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index f5a9dceb782..44944a9fb26 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -579,7 +579,6 @@ impl EntryKind {
             EntryKind::ConstParam => DefKind::ConstParam,
             EntryKind::OpaqueTy => DefKind::OpaqueTy,
             EntryKind::AssocType(_) => DefKind::AssocTy,
-            EntryKind::AssocOpaqueTy(_) => DefKind::AssocOpaqueTy,
             EntryKind::Mod(_) => DefKind::Mod,
             EntryKind::Variant(_) => DefKind::Variant,
             EntryKind::Trait(_) => DefKind::Trait,
@@ -1145,7 +1144,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 (ty::AssocKind::Fn, data.container, data.has_self)
             }
             EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false),
-            EntryKind::AssocOpaqueTy(container) => (ty::AssocKind::OpaqueTy, container, false),
             _ => bug!("cannot get associated-item of `{:?}`", def_key),
         };
 
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 64ccd46a744..1dc22c10c8e 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -874,7 +874,6 @@ impl EncodeContext<'tcx> {
                 }))
             }
             ty::AssocKind::Type => EntryKind::AssocType(container),
-            ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"),
         });
         record!(self.tables.visibility[def_id] <- trait_item.vis);
         record!(self.tables.span[def_id] <- ast_item.span);
@@ -892,7 +891,6 @@ impl EncodeContext<'tcx> {
                     self.encode_item_type(def_id);
                 }
             }
-            ty::AssocKind::OpaqueTy => unreachable!(),
         }
         if trait_item.kind == ty::AssocKind::Fn {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
@@ -957,7 +955,6 @@ impl EncodeContext<'tcx> {
                     has_self: impl_item.fn_has_self_parameter,
                 }))
             }
-            ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container),
             ty::AssocKind::Type => EntryKind::AssocType(container)
         });
         record!(self.tables.visibility[def_id] <- impl_item.vis);
@@ -989,7 +986,7 @@ impl EncodeContext<'tcx> {
                 let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                 needs_inline || is_const_fn || always_encode_mir
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => false,
+            hir::ImplItemKind::TyAlias(..) => false,
         };
         if mir {
             self.encode_optimized_mir(def_id.expect_local());
@@ -1786,7 +1783,7 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
                     self.prefetch_mir(def_id)
                 }
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => (),
+            hir::ImplItemKind::TyAlias(..) => (),
         }
     }
 }
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 89d525eb80b..626a436b400 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -308,7 +308,6 @@ enum EntryKind {
     Impl(Lazy<ImplData>),
     AssocFn(Lazy<AssocFnData>),
     AssocType(AssocContainer),
-    AssocOpaqueTy(AssocContainer),
     AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
     TraitAlias,
 }
diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs
index b1dafb3c885..d1cfc4867a2 100644
--- a/src/librustc_middle/hir/map/mod.rs
+++ b/src/librustc_middle/hir/map/mod.rs
@@ -228,7 +228,6 @@ impl<'hir> Map<'hir> {
                 ImplItemKind::Const(..) => DefKind::AssocConst,
                 ImplItemKind::Fn(..) => DefKind::AssocFn,
                 ImplItemKind::TyAlias(..) => DefKind::AssocTy,
-                ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy,
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
@@ -672,6 +671,8 @@ impl<'hir> Map<'hir> {
             if let Node::Item(Item {
                 kind:
                     ItemKind::Fn(..)
+                    | ItemKind::Const(..)
+                    | ItemKind::Static(..)
                     | ItemKind::Mod(..)
                     | ItemKind::Enum(..)
                     | ItemKind::Struct(..)
@@ -700,11 +701,7 @@ impl<'hir> Map<'hir> {
                 return CRATE_HIR_ID;
             }
             match self.get(scope) {
-                Node::Item(Item {
-                    kind: ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }),
-                    ..
-                })
-                | Node::Block(_) => {}
+                Node::Block(_) => {}
                 _ => break,
             }
         }
@@ -1025,9 +1022,6 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
             ImplItemKind::TyAlias(_) => {
                 format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
             }
-            ImplItemKind::OpaqueTy(_) => {
-                format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str)
-            }
         },
         Some(Node::TraitItem(ti)) => {
             let kind = match ti.kind {
diff --git a/src/librustc_middle/traits/specialization_graph.rs b/src/librustc_middle/traits/specialization_graph.rs
index 4f02aaa96ac..f4961617b81 100644
--- a/src/librustc_middle/traits/specialization_graph.rs
+++ b/src/librustc_middle/traits/specialization_graph.rs
@@ -100,24 +100,11 @@ impl<'tcx> Node {
         trait_item_kind: ty::AssocKind,
         trait_def_id: DefId,
     ) -> Option<ty::AssocItem> {
-        use crate::ty::AssocKind::*;
-
         tcx.associated_items(self.def_id())
             .filter_by_name_unhygienic(trait_item_name.name)
             .find(move |impl_item| {
-                match (trait_item_kind, impl_item.kind) {
-                | (Const, Const)
-                | (Fn, Fn)
-                | (Type, Type)
-                | (Type, OpaqueTy)  // assoc. types can be made opaque in impls
-                => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id),
-
-                | (Const, _)
-                | (Fn, _)
-                | (Type, _)
-                | (OpaqueTy, _)
-                => false,
-            }
+                trait_item_kind == impl_item.kind
+                    && tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id)
             })
             .copied()
     }
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index 480420dfdcf..be3bf748225 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -814,7 +814,7 @@ fn foo(&self) -> Self::T { String::new() }
                 // FIXME: account for `#![feature(specialization)]`
                 for item in &items[..] {
                     match item.kind {
-                        hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => {
+                        hir::AssocItemKind::Type => {
                             // FIXME: account for returning some type in a trait fn impl that has
                             // an assoc type as a return type (#72076).
                             if let hir::Defaultness::Default { has_value: true } = item.defaultness
@@ -838,7 +838,7 @@ fn foo(&self) -> Self::T { String::new() }
             })) => {
                 for item in &items[..] {
                     match item.kind {
-                        hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => {
+                        hir::AssocItemKind::Type => {
                             if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
                                 db.span_label(item.span, "expected this associated type");
                                 return true;
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index caa1b4cb375..93ef7317199 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -198,14 +198,13 @@ pub struct AssocItem {
 pub enum AssocKind {
     Const,
     Fn,
-    OpaqueTy,
     Type,
 }
 
 impl AssocKind {
     pub fn namespace(&self) -> Namespace {
         match *self {
-            ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::TypeNS,
+            ty::AssocKind::Type => Namespace::TypeNS,
             ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
         }
     }
@@ -215,22 +214,11 @@ impl AssocKind {
             AssocKind::Const => DefKind::AssocConst,
             AssocKind::Fn => DefKind::AssocFn,
             AssocKind::Type => DefKind::AssocTy,
-            AssocKind::OpaqueTy => DefKind::AssocOpaqueTy,
         }
     }
 }
 
 impl AssocItem {
-    /// Tests whether the associated item admits a non-trivial implementation
-    /// for !
-    pub fn relevant_for_never(&self) -> bool {
-        match self.kind {
-            AssocKind::OpaqueTy | AssocKind::Const | AssocKind::Type => true,
-            // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
-            AssocKind::Fn => !self.fn_has_self_parameter,
-        }
-    }
-
     pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
         match self.kind {
             ty::AssocKind::Fn => {
@@ -241,8 +229,6 @@ impl AssocItem {
                 tcx.fn_sig(self.def_id).skip_binder().to_string()
             }
             ty::AssocKind::Type => format!("type {};", self.ident),
-            // FIXME(type_alias_impl_trait): we should print bounds here too.
-            ty::AssocKind::OpaqueTy => format!("type {};", self.ident),
             ty::AssocKind::Const => {
                 format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id))
             }
@@ -2581,10 +2567,6 @@ impl<'tcx> TyCtxt<'tcx> {
             .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value())
     }
 
-    pub fn trait_relevant_for_never(self, did: DefId) -> bool {
-        self.associated_items(did).in_definition_order().any(|item| item.relevant_for_never())
-    }
-
     pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
         def_id
             .as_local()
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index f97dff14645..5707127340d 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -259,7 +259,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
-                    .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
+                    .unwrap_or_else(|_| {
+                        self.infcx
+                            .tcx
+                            .sess
+                            .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
+                        (self.infcx.tcx.types.err, None)
+                    });
                 let constraints2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
                 constraints1.into_iter().chain(constraints2)
diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index b54731d8881..80681c14375 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -37,7 +37,7 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>)
                 Target::Method(MethodKind::Inherent)
             }
         }
-        hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::OpaqueTy(..) => Target::AssocTy,
+        hir::ImplItemKind::TyAlias(..) => Target::AssocTy,
     }
 }
 
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 1dcf0e7c7a9..503fbb64db8 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -304,7 +304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-        if let TyKind::Def(item_id, _) = ty.kind {
+        if let TyKind::OpaqueDef(item_id, _) = ty.kind {
             let item = self.tcx.hir().expect_item(item_id.id);
             intravisit::walk_item(self, item);
         }
@@ -668,7 +668,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 }
                 self.visit_nested_body(body_id)
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => {}
+            hir::ImplItemKind::TyAlias(..) => {}
         }
     }
 
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index c0826f8cc60..2419e696596 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -27,8 +27,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
             ItemKind::TyAlias(..)
             | ItemKind::Enum(..)
             | ItemKind::Struct(..)
-            | ItemKind::Union(..)
-            | ItemKind::OpaqueTy(..) => {
+            | ItemKind::Union(..) => {
                 for attr in self.tcx.get_attrs(item_def_id.to_def_id()).iter() {
                     if attr.check_name(sym::rustc_layout) {
                         self.dump_layout_of(item_def_id, item, attr);
@@ -83,9 +82,11 @@ impl LayoutTest<'tcx> {
                         }
 
                         sym::debug => {
+                            let normalized_ty =
+                                self.tcx.normalize_erasing_regions(param_env.with_reveal_all(), ty);
                             self.tcx.sess.span_err(
                                 item.span,
-                                &format!("layout_of({:?}) = {:#?}", ty, *ty_layout),
+                                &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),
                             );
                         }
 
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index cac71b3836c..c9a4428c007 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -180,7 +180,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             }
                         }
                     }
-                    hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => false,
+                    hir::ImplItemKind::TyAlias(_) => false,
                 }
             }
             Some(_) => false,
@@ -289,7 +289,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                         self.visit_nested_body(body)
                     }
                 }
-                hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {}
+                hir::ImplItemKind::TyAlias(_) => {}
             },
             Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => {
                 self.visit_nested_body(body);
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index d54ec2eca8c..3c1b56a9ef4 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -615,7 +615,6 @@ impl EmbargoVisitor<'tcx> {
             // public, or are not namespaced at all.
             DefKind::AssocConst
             | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
             | DefKind::ConstParam
             | DefKind::Ctor(_, _)
             | DefKind::Enum
@@ -1333,11 +1332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             _ => None,
         };
         let def = def.filter(|(kind, _)| match kind {
-            DefKind::AssocFn
-            | DefKind::AssocConst
-            | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
-            | DefKind::Static => true,
+            DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true,
             _ => false,
         });
         if let Some((kind, def_id)) = def {
@@ -1602,9 +1597,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                             hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
                                 self.access_levels.is_reachable(impl_item_ref.id.hir_id)
                             }
-                            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
-                                false
-                            }
+                            hir::ImplItemKind::TyAlias(_) => false,
                         }
                     });
 
@@ -1952,9 +1945,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
         let (check_ty, is_assoc_ty) = match assoc_item_kind {
             AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
             AssocItemKind::Type => (defaultness.has_value(), true),
-            // `ty()` for opaque types is the underlying type,
-            // it's not a part of interface, so we skip it.
-            AssocItemKind::OpaqueTy => (false, true),
         };
         check.in_assoc_ty = is_assoc_ty;
         check.generics().predicates();
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 2ae063660e3..e633bd1843e 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -746,12 +746,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(_, _, _, ref ty) => {
-                let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
-                    None => DefKind::TyAlias,
-                    Some(_) => DefKind::OpaqueTy,
-                };
-                let res = Res::Def(def_kind, self.r.definitions.local_def_id(item.id).to_def_id());
+            ItemKind::TyAlias(..) => {
+                let res = Res::Def(
+                    DefKind::TyAlias,
+                    self.r.definitions.local_def_id(item.id).to_def_id(),
+                );
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
@@ -917,8 +916,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 | DefKind::ForeignTy
                 | DefKind::OpaqueTy
                 | DefKind::TraitAlias
-                | DefKind::AssocTy
-                | DefKind::AssocOpaqueTy,
+                | DefKind::AssocTy,
                 _,
             )
             | Res::PrimTy(..)
diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs
index a3fbb28f22a..5bbf8703f0b 100644
--- a/src/librustc_resolve/late/lifetimes.rs
+++ b/src/librustc_resolve/late/lifetimes.rs
@@ -258,6 +258,9 @@ enum Elide {
     Exact(Region),
     /// Less or more than one lifetime were found, error on unspecified.
     Error(Vec<ElisionFailureInfo>),
+    /// Forbid lifetime elision inside of a larger scope where it would be
+    /// permitted. For example, in let position impl trait.
+    Forbid,
 }
 
 #[derive(Clone, Debug)]
@@ -396,15 +399,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let scope = Scope::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE };
                 self.with(scope, |_, this| intravisit::walk_item(this, item));
             }
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {
-                // Currently opaque type declarations are just generated from `impl Trait`
-                // items. Doing anything on this node is irrelevant, as we currently don't need
-                // it.
+            hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
+                // Opaque types are visited when we visit the
+                // `TyKind::OpaqueDef`, so that they have the lifetimes from
+                // their parent opaque_ty in scope.
             }
             hir::ItemKind::TyAlias(_, ref generics)
-            | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                impl_trait_fn: None, ref generics, ..
-            })
             | hir::ItemKind::Enum(_, ref generics)
             | hir::ItemKind::Struct(_, ref generics)
             | hir::ItemKind::Union(_, ref generics)
@@ -557,23 +557,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 };
                 self.with(scope, |_, this| this.visit_ty(&mt.ty));
             }
-            hir::TyKind::Def(item_id, lifetimes) => {
+            hir::TyKind::OpaqueDef(item_id, lifetimes) => {
                 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
                 //                 ^                  ^ this gets resolved in the scope of
                 //                                      the opaque_ty generics
-                let (generics, bounds) = match self.tcx.hir().expect_item(item_id.id).kind {
+                let opaque_ty = self.tcx.hir().expect_item(item_id.id);
+                let (generics, bounds) = match opaque_ty.kind {
                     // Named opaque `impl Trait` types are reached via `TyKind::Path`.
                     // This arm is for `impl Trait` in the types of statics, constants and locals.
                     hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
                         intravisit::walk_ty(self, ty);
+
+                        // Elided lifetimes are not allowed in non-return
+                        // position impl Trait
+                        let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope };
+                        self.with(scope, |_, this| {
+                            intravisit::walk_item(this, opaque_ty);
+                        });
+
                         return;
                     }
                     // RPIT (return position impl trait)
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, bounds, .. }) => {
-                        (generics, bounds)
-                    }
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                        impl_trait_fn: Some(_),
+                        ref generics,
+                        bounds,
+                        ..
+                    }) => (generics, bounds),
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 };
 
@@ -797,43 +809,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     this.visit_ty(ty);
                 });
             }
-            OpaqueTy(bounds) => {
-                let generics = &impl_item.generics;
-                let mut index = self.next_early_index();
-                let mut next_early_index = index;
-                debug!("visit_ty: index = {}", index);
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            Some(Region::early(&self.tcx.hir(), &mut index, param))
-                        }
-                        GenericParamKind::Type { .. } => {
-                            next_early_index += 1;
-                            None
-                        }
-                        GenericParamKind::Const { .. } => {
-                            next_early_index += 1;
-                            None
-                        }
-                    })
-                    .collect();
-
-                let scope = Scope::Binder {
-                    lifetimes,
-                    next_early_index,
-                    s: self.scope,
-                    track_lifetime_uses: true,
-                    opaque_type_parent: true,
-                };
-                self.with(scope, |_old_scope, this| {
-                    this.visit_generics(generics);
-                    for bound in bounds {
-                        this.visit_param_bound(bound);
-                    }
-                });
-            }
             Const(_, _) => {
                 // Only methods and types support generics.
                 assert!(impl_item.generics.params.is_empty());
@@ -2367,6 +2342,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                             }
                             break Some(e);
                         }
+                        Elide::Forbid => break None,
                     };
                     for lifetime_ref in lifetime_refs {
                         self.insert_lifetime(lifetime_ref, lifetime);
@@ -2667,8 +2643,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 // going to make a fresh name, so we cannot
                 // necessarily replace a single-use lifetime with
                 // `'_`.
-                Scope::Elision { elide: Elide::Exact(_), .. } => break false,
-                Scope::Elision { elide: Elide::Error(_), .. } => break false,
+                Scope::Elision {
+                    elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, ..
+                } => break false,
 
                 Scope::ObjectLifetimeDefault { s, .. } => scope = s,
             }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 9b08f709f34..e63e31e03c9 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1102,7 +1102,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     impl_item.span,
                 );
             }
-            hir::ImplItemKind::OpaqueTy(..) => {}
             hir::ImplItemKind::TyAlias(ref ty) => {
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
@@ -1380,7 +1379,7 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
                     v.visit_expr(&map.body(anon_const.body).value)
                 });
             }
-            hir::TyKind::Def(item_id, _) => {
+            hir::TyKind::OpaqueDef(item_id, _) => {
                 let item = self.tcx.hir().item(item_id.id);
                 self.nest_tables(self.tcx.hir().local_def_id(item_id.id), |v| v.visit_item(item));
             }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index eb35d74729a..12d2c8c7eb9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -698,7 +698,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                 | HirDefKind::TyAlias
                 | HirDefKind::ForeignTy
                 | HirDefKind::TraitAlias
-                | HirDefKind::AssocOpaqueTy
                 | HirDefKind::AssocTy
                 | HirDefKind::Trait
                 | HirDefKind::OpaqueTy
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 5f337f5f770..cd2a5deeb2d 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -324,7 +324,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
                 let text = format!("[{}; {}]", nested_ty.text, expr);
                 Ok(replace_text(nested_ty, text))
             }
-            hir::TyKind::Def(item_id, _) => {
+            hir::TyKind::OpaqueDef(item_id, _) => {
                 let item = scx.tcx.hir().item(item_id.id);
                 item.make(offset, Some(item_id.id), scx)
             }
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index 19caf64c63f..d53a0ec9ef8 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -11,7 +11,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{self, InferCtxt, InferOk};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::nightly_options;
 use rustc_span::Span;
 
@@ -133,9 +133,9 @@ pub trait InferCtxtExt<'tcx> {
     fn generate_member_constraint(
         &self,
         concrete_ty: Ty<'tcx>,
-        opaque_type_generics: &ty::Generics,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         opaque_type_def_id: DefId,
+        first_own_region_index: usize,
     );
 
     /*private*/
@@ -405,7 +405,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
 
-        let opaque_type_generics = tcx.generics_of(def_id);
+        let first_own_region = match opaque_defn.origin {
+            hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
+                // We lower
+                //
+                // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+                //
+                // into
+                //
+                // type foo::<'p0..'pn>::Foo<'q0..'qm>
+                // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+                //
+                // For these types we onlt iterate over `'l0..lm` below.
+                tcx.generics_of(def_id).parent_count
+            }
+            // These opaque type inherit all lifetime parameters from their
+            // parent, so we have to check them all.
+            hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
+        };
 
         let span = tcx.def_span(def_id);
 
@@ -427,12 +444,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 });
             }
             if let GenerateMemberConstraints::IfNoStaticBound = mode {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
+                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
             }
             return;
         }
@@ -445,29 +457,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // `['a]` for the first impl trait and `'b` for the
         // second.
         let mut least_region = None;
-        for param in &opaque_type_generics.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                _ => continue,
-            }
 
-            // Get the value supplied for this region from the substs.
-            let subst_arg = opaque_defn.substs.region_at(param.index as usize);
+        for subst_arg in &opaque_defn.substs[first_own_region..] {
+            let subst_region = match subst_arg.unpack() {
+                GenericArgKind::Lifetime(r) => r,
+                GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue,
+            };
 
             // Compute the least upper bound of it with the other regions.
             debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_arg={:?}", subst_arg);
+            debug!("constrain_opaque_types: subst_region={:?}", subst_region);
             match least_region {
-                None => least_region = Some(subst_arg),
+                None => least_region = Some(subst_region),
                 Some(lr) => {
-                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_arg) {
+                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_region) {
                         // keep the current least region
-                    } else if free_region_relations.sub_free_regions(self.tcx, subst_arg, lr) {
-                        // switch to `subst_arg`
-                        least_region = Some(subst_arg);
+                    } else if free_region_relations.sub_free_regions(self.tcx, subst_region, lr) {
+                        // switch to `subst_region`
+                        least_region = Some(subst_region);
                     } else {
                         // There are two regions (`lr` and
-                        // `subst_arg`) which are not relatable. We
+                        // `subst_region`) which are not relatable. We
                         // can't find a best choice. Therefore,
                         // instead of creating a single bound like
                         // `'r: 'a` (which is our preferred choice),
@@ -476,13 +486,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         // regions that appear in the impl trait.
 
                         // For now, enforce a feature gate outside of async functions.
-                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
+                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_region);
 
                         return self.generate_member_constraint(
                             concrete_ty,
-                            opaque_type_generics,
                             opaque_defn,
                             def_id,
+                            first_own_region,
                         );
                     }
                 }
@@ -494,12 +504,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
+                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
             }
         }
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
@@ -518,22 +523,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     fn generate_member_constraint(
         &self,
         concrete_ty: Ty<'tcx>,
-        opaque_type_generics: &ty::Generics,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         opaque_type_def_id: DefId,
+        first_own_region: usize,
     ) {
         // Create the set of choice regions: each region in the hidden
         // type can be equal to any of the region parameters of the
         // opaque type definition.
         let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
-            opaque_type_generics
-                .params
+            opaque_defn.substs[first_own_region..]
                 .iter()
-                .filter(|param| match param.kind {
-                    GenericParamDefKind::Lifetime => true,
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
+                .filter_map(|arg| match arg.unpack() {
+                    GenericArgKind::Lifetime(r) => Some(r),
+                    GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
                 })
-                .map(|param| opaque_defn.substs.region_at(param.index as usize))
                 .chain(std::iter::once(self.tcx.lifetimes.re_static))
                 .collect(),
         );
@@ -574,7 +577,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             hir::OpaqueTyOrigin::AsyncFn => return false,
 
             // Otherwise, generate the label we'll use in the error message.
-            hir::OpaqueTyOrigin::TypeAlias
+            hir::OpaqueTyOrigin::Binding
             | hir::OpaqueTyOrigin::FnReturn
             | hir::OpaqueTyOrigin::Misc => "impl Trait",
         };
@@ -1064,21 +1067,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                                     ),
                                     origin,
                                 ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
-                            },
-                            Some(Node::ImplItem(item)) => match item.kind {
-                                hir::ImplItemKind::OpaqueTy(_) => (
-                                    may_define_opaque_type(
-                                        tcx,
-                                        self.parent_def_id.expect_local(),
-                                        opaque_hir_id,
-                                    ),
-                                    hir::OpaqueTyOrigin::TypeAlias,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
                             },
                             _ => bug!(
-                                "expected (impl) item, found {}",
+                                "expected item, found {}",
                                 tcx.hir().node_to_string(opaque_hir_id),
                             ),
                         };
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index d6c79d1973a..9492c3c3409 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -25,7 +25,7 @@ use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_span::symbol::{sym, Ident};
@@ -1477,12 +1477,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
     let substs =
         translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
-    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
-        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
-    } else {
-        tcx.type_of(assoc_ty.item.def_id)
-    };
+    let ty = tcx.type_of(assoc_ty.item.def_id);
     if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
         tcx.sess
             .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
@@ -1515,7 +1510,7 @@ fn assoc_ty_def(
     // cycle error if the specialization graph is currently being built.
     let impl_node = specialization_graph::Node::Impl(impl_def_id);
     for item in impl_node.items(tcx) {
-        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
+        if matches!(item.kind, ty::AssocKind::Type)
             && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
         {
             return Ok(specialization_graph::LeafDef {
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 3da5da2d9ef..99094246a63 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -85,7 +85,6 @@ fn associated_item_from_trait_item_ref(
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
         hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-        hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
     };
 
     ty::AssocItem {
@@ -110,7 +109,6 @@ fn associated_item_from_impl_item_ref(
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
         hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-        hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
     };
 
     ty::AssocItem {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index f1dc7e53906..267f3d9f3ef 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2838,9 +2838,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
                 self.res_to_ty(opt_self_ty, path, false)
             }
-            hir::TyKind::Def(item_id, ref lifetimes) => {
-                let did = tcx.hir().local_def_id(item_id.id);
-                self.impl_trait_ty_to_ty(did.to_def_id(), lifetimes)
+            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
+                let opaque_ty = tcx.hir().expect_item(item_id.id);
+                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+
+                match opaque_ty.kind {
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
+                    }
+                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+                }
             }
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
@@ -2893,6 +2900,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         def_id: DefId,
         lifetimes: &[hir::GenericArg<'_>],
+        replace_parent_lifetimes: bool,
     ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
@@ -2914,9 +2922,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     _ => bug!(),
                 }
             } else {
-                // Replace all parent lifetimes with `'static`.
                 match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+                    // For RPIT (return position impl trait), only lifetimes
+                    // mentioned in the impl Trait predicate are captured by
+                    // the opaque type, so the lifetime parameters from the
+                    // parent item need to be replaced with `'static`.
+                    //
+                    // For `impl Trait` in the types of statics, constants,
+                    // locals and type aliases. These capture all parent
+                    // lifetimes, so they can use their identity subst.
+                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
+                        tcx.lifetimes.re_static.into()
+                    }
                     _ => tcx.mk_param_from_def(param),
                 }
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 96c0d98ab06..15ec92568fb 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let mut is_object_safe = false;
         if let hir::FnRetTy::Return(ty) = fn_output {
             // Get the return type.
-            if let hir::TyKind::Def(..) = ty.kind {
+            if let hir::TyKind::OpaqueDef(..) = ty.kind {
                 let ty = AstConv::ast_ty_to_ty(fcx, ty);
                 // Get the `impl Trait`'s `DefId`.
                 if let ty::Opaque(def_id, _) = ty.kind {
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 29cd9681295..5f8fcaadfdb 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1165,6 +1165,6 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
     match impl_item.kind {
         ty::AssocKind::Const => "const",
         ty::AssocKind::Fn => "method",
-        ty::AssocKind::Type | ty::AssocKind::OpaqueTy => "type",
+        ty::AssocKind::Type => "type",
     }
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4095ab5e10f..a2e6c8793cb 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1556,7 +1556,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         match self.mode {
             Mode::MethodCall => item.fn_has_self_parameter,
             Mode::Path => match item.kind {
-                ty::AssocKind::OpaqueTy | ty::AssocKind::Type => false,
+                ty::AssocKind::Type => false,
                 ty::AssocKind::Fn | ty::AssocKind::Const => true,
             },
         }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 7ca3eb884d8..67bdd04d371 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -158,9 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             let path = self.tcx.def_path_str(trait_ref.def_id);
 
                             let ty = match item.kind {
-                                ty::AssocKind::Const
-                                | ty::AssocKind::Type
-                                | ty::AssocKind::OpaqueTy => rcvr_ty,
+                                ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
                                 ty::AssocKind::Fn => self
                                     .tcx
                                     .fn_sig(item.def_id)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fabedc3800a..7b8f1802196 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1943,7 +1943,6 @@ fn check_specialization_validity<'tcx>(
     let kind = match impl_item.kind {
         hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
         hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
-        hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy,
         hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
     };
 
@@ -2114,7 +2113,7 @@ fn check_impl_items_against_trait<'tcx>(
                         err.emit()
                     }
                 }
-                hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
+                hir::ImplItemKind::TyAlias(_) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Type {
                         compare_ty_impl(
@@ -2367,8 +2366,6 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
             )
         }
         ty::AssocKind::Type => format!("type {} = Type;", assoc.ident),
-        // FIXME(type_alias_impl_trait): we should print bounds here too.
-        ty::AssocKind::OpaqueTy => format!("type {} = Type;", assoc.ident),
         ty::AssocKind::Const => {
             let ty = tcx.type_of(assoc.def_id);
             let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 7d9bf975c69..f3297ed6743 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -316,9 +316,6 @@ fn check_associated_item(
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
-            ty::AssocKind::OpaqueTy => {
-                // Do nothing: opaque types check themselves.
-            }
         }
 
         implied_bounds
@@ -804,14 +801,14 @@ fn check_where_clauses<'tcx, 'fcx>(
             traits::Obligation::new(cause, fcx.param_env, pred)
         });
 
-    let mut predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = predicates.instantiate_identity(fcx.tcx);
 
-    if let Some((return_ty, span)) = return_ty {
-        let opaque_types = check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
-        for _ in 0..opaque_types.len() {
-            predicates.spans.push(span);
+    if let Some((mut return_ty, span)) = return_ty {
+        if return_ty.has_infer_types_or_consts() {
+            fcx.select_obligations_where_possible(false, |_| {});
+            return_ty = fcx.resolve_vars_if_possible(&return_ty);
         }
-        predicates.predicates.extend(opaque_types);
+        check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
     }
 
     let predicates = fcx.normalize_associated_types_in(span, &predicates);
@@ -883,119 +880,117 @@ fn check_opaque_types<'fcx, 'tcx>(
     fn_def_id: LocalDefId,
     span: Span,
     ty: Ty<'tcx>,
-) -> Vec<ty::Predicate<'tcx>> {
+) {
     trace!("check_opaque_types(ty={:?})", ty);
-    let mut substituted_predicates = Vec::new();
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
         ty_op: |ty| {
             if let ty::Opaque(def_id, substs) = ty.kind {
                 trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
-                // Only check named `impl Trait` types defined in this crate.
-                // FIXME(eddyb) is  `generics.parent.is_none()` correct? It seems
-                // potentially risky wrt associated types in `impl`s.
-                if generics.parent.is_none() && def_id.is_local() {
-                    let opaque_hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
-                    if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
-                        trace!("check_opaque_types: may define, generics={:#?}", generics);
-                        let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
-                        for (i, arg) in substs.iter().enumerate() {
-                            let arg_is_param = match arg.unpack() {
-                                GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
-
-                                GenericArgKind::Lifetime(region) => {
-                                    if let ty::ReStatic = region {
-                                        tcx.sess
-                                            .struct_span_err(
-                                                span,
-                                                "non-defining opaque type use in defining scope",
-                                            )
-                                            .span_label(
-                                                tcx.def_span(generics.param_at(i, tcx).def_id),
-                                                "cannot use static lifetime; use a bound lifetime \
-                                                 instead or remove the lifetime parameter from the \
-                                                 opaque type",
-                                            )
-                                            .emit();
-                                        continue;
-                                    }
-
-                                    true
-                                }
-
-                                GenericArgKind::Const(ct) => {
-                                    matches!(ct.val, ty::ConstKind::Param(_))
-                                }
-                            };
-
-                            if arg_is_param {
-                                seen_params.entry(arg).or_default().push(i);
-                            } else {
-                                // Prevent `fn foo() -> Foo<u32>` from being defining.
-                                let opaque_param = generics.param_at(i, tcx);
+
+                let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
+                    tcx.hir().as_local_hir_id(local_id)
+                } else {
+                    // Opaque types from other crates won't have defining uses in this crate.
+                    return ty;
+                };
+                if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
+                    tcx.hir().expect_item(opaque_hir_id).kind
+                {
+                    // No need to check return position impl trait (RPIT)
+                    // because for type and const parameters they are correct
+                    // by construction: we convert
+                    //
+                    // fn foo<P0..Pn>() -> impl Trait
+                    //
+                    // into
+                    //
+                    // type Foo<P0...Pn>
+                    // fn foo<P0..Pn>() -> Foo<P0...Pn>.
+                    //
+                    // For lifetime parameters we convert
+                    //
+                    // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+                    //
+                    // into
+                    //
+                    // type foo::<'p0..'pn>::Foo<'q0..'qm>
+                    // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+                    //
+                    // which would error here on all of the `'static` args.
+                    return ty;
+                }
+                if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
+                    return ty;
+                }
+                trace!("check_opaque_types: may define, generics={:#?}", generics);
+                let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+                for (i, arg) in substs.iter().enumerate() {
+                    let arg_is_param = match arg.unpack() {
+                        GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
+
+                        GenericArgKind::Lifetime(region) => {
+                            if let ty::ReStatic = region {
                                 tcx.sess
                                     .struct_span_err(
                                         span,
                                         "non-defining opaque type use in defining scope",
                                     )
-                                    .span_note(
-                                        tcx.def_span(opaque_param.def_id),
-                                        &format!(
-                                            "used non-generic {} `{}` for generic parameter",
-                                            opaque_param.kind.descr(),
-                                            arg,
-                                        ),
-                                    )
-                                    .emit();
-                            }
-                        } // for (arg, param)
-
-                        for (_, indices) in seen_params {
-                            if indices.len() > 1 {
-                                let descr = generics.param_at(indices[0], tcx).kind.descr();
-                                let spans: Vec<_> = indices
-                                    .into_iter()
-                                    .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
-                                    .collect();
-                                tcx.sess
-                                    .struct_span_err(
-                                        span,
-                                        "non-defining opaque type use in defining scope",
+                                    .span_label(
+                                        tcx.def_span(generics.param_at(i, tcx).def_id),
+                                        "cannot use static lifetime; use a bound lifetime \
+                                                 instead or remove the lifetime parameter from the \
+                                                 opaque type",
                                     )
-                                    .span_note(spans, &format!("{} used multiple times", descr))
                                     .emit();
+                                continue;
                             }
-                        }
-                    } // if may_define_opaque_type
 
-                    // Now register the bounds on the parameters of the opaque type
-                    // so the parameters given by the function need to fulfill them.
-                    //
-                    //     type Foo<T: Bar> = impl Baz + 'static;
-                    //     fn foo<U>() -> Foo<U> { .. *}
-                    //
-                    // becomes
-                    //
-                    //     type Foo<T: Bar> = impl Baz + 'static;
-                    //     fn foo<U: Bar>() -> Foo<U> { .. *}
-                    let predicates = tcx.predicates_of(def_id);
-                    trace!("check_opaque_types: may define, predicates={:#?}", predicates,);
-                    for &(pred, _) in predicates.predicates {
-                        let substituted_pred = pred.subst(fcx.tcx, substs);
-                        // Avoid duplication of predicates that contain no parameters, for example.
-                        if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
-                            substituted_predicates.push(substituted_pred);
+                            true
                         }
+
+                        GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
+                    };
+
+                    if arg_is_param {
+                        seen_params.entry(arg).or_default().push(i);
+                    } else {
+                        // Prevent `fn foo() -> Foo<u32>` from being defining.
+                        let opaque_param = generics.param_at(i, tcx);
+                        tcx.sess
+                            .struct_span_err(span, "non-defining opaque type use in defining scope")
+                            .span_note(
+                                tcx.def_span(opaque_param.def_id),
+                                &format!(
+                                    "used non-generic {} `{}` for generic parameter",
+                                    opaque_param.kind.descr(),
+                                    arg,
+                                ),
+                            )
+                            .emit();
                     }
-                } // if is_named_opaque_type
+                } // for (arg, param)
+
+                for (_, indices) in seen_params {
+                    if indices.len() > 1 {
+                        let descr = generics.param_at(indices[0], tcx).kind.descr();
+                        let spans: Vec<_> = indices
+                            .into_iter()
+                            .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
+                            .collect();
+                        tcx.sess
+                            .struct_span_err(span, "non-defining opaque type use in defining scope")
+                            .span_note(spans, &format!("{} used multiple times", descr))
+                            .emit();
+                    }
+                }
             } // if let Opaque
             ty
         },
         lt_op: |lt| lt,
         ct_op: |ct| ct,
     });
-    substituted_predicates
 }
 
 const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 3473dc7a58d..159d3d7a538 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -460,7 +460,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let mut skip_add = false;
 
             if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind {
-                if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin {
+                if let hir::OpaqueTyOrigin::Misc = opaque_defn.origin {
                     if def_id == defin_ty_def_id {
                         debug!(
                             "skipping adding concrete definition for opaque type {:?} {:?}",
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 355b4fc413f..1d59d749634 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -742,7 +742,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
         hir::ImplItemKind::Fn(..) => {
             tcx.ensure().fn_sig(def_id);
         }
-        hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => {
+        hir::ImplItemKind::TyAlias(_) => {
             // Account for `type T = _;`
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_impl_item(impl_item);
@@ -1202,22 +1202,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
                 impl_trait_fn.or_else(|| {
                     let parent_id = tcx.hir().get_parent_item(hir_id);
-                    if parent_id != hir_id && parent_id != CRATE_HIR_ID {
-                        debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
-                        // If this 'impl Trait' is nested inside another 'impl Trait'
-                        // (e.g. `impl Foo<MyType = impl Bar<A>>`), we need to use the 'parent'
-                        // 'impl Trait' for its generic parameters, since we can reference them
-                        // from the 'child' 'impl Trait'
-                        if let Node::Item(hir::Item { kind: ItemKind::OpaqueTy(..), .. }) =
-                            tcx.hir().get(parent_id)
-                        {
-                            Some(tcx.hir().local_def_id(parent_id).to_def_id())
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    }
+                    assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID);
+                    debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
+                    // Opaque types are always nested within another item, and
+                    // inherit the generics of the item.
+                    Some(tcx.hir().local_def_id(parent_id).to_def_id())
                 })
             }
             _ => None,
@@ -1428,7 +1417,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
         Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
         Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
         Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
-        Def(_, generic_args) => are_suggestable_generic_args(generic_args),
+        OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
         Path(hir::QPath::TypeRelative(ty, segment)) => {
             is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.generic_args().args)
         }
@@ -1715,31 +1704,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     let ast_generics = match node {
         Node::TraitItem(item) => &item.generics,
 
-        Node::ImplItem(item) => match item.kind {
-            ImplItemKind::OpaqueTy(ref bounds) => {
-                ty::print::with_no_queries(|| {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    let opaque_ty = tcx.mk_opaque(def_id, substs);
-                    debug!(
-                        "explicit_predicates_of({:?}): created opaque type {:?}",
-                        def_id, opaque_ty
-                    );
-
-                    // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
-                    let bounds = AstConv::compute_bounds(
-                        &icx,
-                        opaque_ty,
-                        bounds,
-                        SizedByDefault::Yes,
-                        tcx.def_span(def_id),
-                    );
-
-                    predicates.extend(bounds.predicates(tcx, opaque_ty));
-                    &item.generics
-                })
-            }
-            _ => &item.generics,
-        },
+        Node::ImplItem(item) => &item.generics,
 
         Node::Item(item) => {
             match item.kind {
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index cf0e3f9cdf5..549a20531e2 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -64,13 +64,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     icx.to_ty(ty)
                 }
             }
-            ImplItemKind::OpaqueTy(_) => {
-                if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
-                    report_assoc_ty_on_inherent_impl(tcx, item.span);
-                }
-
-                find_opaque_ty_constraints(tcx, def_id.expect_local())
-            }
             ImplItemKind::TyAlias(ref ty) => {
                 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
                     report_assoc_ty_on_inherent_impl(tcx, item.span);
@@ -107,26 +100,17 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
+                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
+                    let_position_impl_trait_type(tcx, def_id.expect_local())
+                }
                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
                     find_opaque_ty_constraints(tcx, def_id.expect_local())
                 }
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => {
-                    let concrete_types = match origin {
-                        OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => {
-                            &tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types
-                        }
-                        OpaqueTyOrigin::Misc => {
-                            // We shouldn't leak borrowck results through impl trait in bindings.
-                            // For example, we shouldn't be able to tell if `x` in
-                            // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`.
-                            &tcx.typeck_tables_of(owner.expect_local()).concrete_opaque_types
-                        }
-                        OpaqueTyOrigin::TypeAlias => {
-                            span_bug!(item.span, "Type alias impl trait shouldn't have an owner")
-                        }
-                    };
-                    let concrete_ty = concrete_types
+                ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
+                    let concrete_ty = tcx
+                        .mir_borrowck(owner.expect_local())
+                        .concrete_opaque_types
                         .get(&def_id)
                         .map(|opaque| opaque.concrete_type)
                         .unwrap_or_else(|| {
@@ -155,13 +139,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                             }
                         });
                     debug!("concrete_ty = {:?}", concrete_ty);
-                    if concrete_ty.has_erased_regions() {
-                        // FIXME(impl_trait_in_bindings) Handle this case.
-                        tcx.sess.span_fatal(
-                            item.span,
-                            "lifetimes in impl Trait types in bindings are not currently supported",
-                        );
-                    }
                     concrete_ty
                 }
                 ItemKind::Trait(..)
@@ -596,6 +573,60 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     }
 }
 
+/// Retrieve the inferred concrete type for let position impl trait.
+///
+/// This is different to other kinds of impl trait because:
+///
+/// 1. We know which function contains the defining use (the function that
+///    contains the let statement)
+/// 2. We do not currently allow (free) lifetimes in the return type. `let`
+///    statements in some statically unreachable code are removed from the MIR
+///    by the time we borrow check, and it's not clear how we should handle
+///    those.
+fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
+    let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
+    let scope_def_id = tcx.hir().local_def_id(scope);
+
+    let opaque_ty_def_id = opaque_ty_id.to_def_id();
+
+    let owner_tables = tcx.typeck_tables_of(scope_def_id);
+    let concrete_ty = owner_tables
+        .concrete_opaque_types
+        .get(&opaque_ty_def_id)
+        .map(|opaque| opaque.concrete_type)
+        .unwrap_or_else(|| {
+            tcx.sess.delay_span_bug(
+                DUMMY_SP,
+                &format!(
+                    "owner {:?} has no opaque type for {:?} in its tables",
+                    scope_def_id, opaque_ty_id
+                ),
+            );
+            if let Some(ErrorReported) = owner_tables.tainted_by_errors {
+                // Some error in the owner fn prevented us from populating the
+                // `concrete_opaque_types` table.
+                tcx.types.err
+            } else {
+                // We failed to resolve the opaque type or it resolves to
+                // itself. Return the non-revealed type, which should result in
+                // E0720.
+                tcx.mk_opaque(
+                    opaque_ty_def_id,
+                    InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
+                )
+            }
+        });
+    debug!("concrete_ty = {:?}", concrete_ty);
+    if concrete_ty.has_erased_regions() {
+        // FIXME(impl_trait_in_bindings) Handle this case.
+        tcx.sess.span_fatal(
+            tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
+            "lifetimes in impl Trait types in bindings are not currently supported",
+        );
+    }
+    concrete_ty
+}
+
 fn infer_placeholder_type(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index e13d9ea2b26..37d383db68a 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -140,13 +140,6 @@ fn enforce_impl_params_are_constrained(
                         Vec::new()
                     }
                 }
-                ty::AssocKind::OpaqueTy => {
-                    // We don't know which lifetimes appear in the actual
-                    // opaque type, so use all of the lifetimes that appear
-                    // in the type's predicates.
-                    let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
-                    cgp::parameters_for(&predicates, true)
-                }
                 ty::AssocKind::Fn | ty::AssocKind::Const => Vec::new(),
             }
         })
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index dd4df11b1df..adb2ae9a5d6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1138,10 +1138,6 @@ impl Clean<Item> for hir::ImplItem<'_> {
                 let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
                 TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
             }
-            hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
-                OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
-                true,
-            ),
         };
         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
         Item {
@@ -1308,7 +1304,6 @@ impl Clean<Item> for ty::AssocItem {
                     )
                 }
             }
-            ty::AssocKind::OpaqueTy => unimplemented!(),
         };
 
         let visibility = match self.container {
@@ -1356,7 +1351,7 @@ impl Clean<Type> for hir::Ty<'_> {
                 Array(box ty.clean(cx), length)
             }
             TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
-            TyKind::Def(item_id, _) => {
+            TyKind::OpaqueDef(item_id, _) => {
                 let item = cx.tcx.hir().expect_item(item_id.id);
                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
                     ImplTrait(ty.bounds.clean(cx))
diff --git a/src/test/rustdoc/auxiliary/issue-73061.rs b/src/test/rustdoc/auxiliary/issue-73061.rs
new file mode 100644
index 00000000000..e05a3bc6d91
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-73061.rs
@@ -0,0 +1,17 @@
+//edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Foo {
+    type X: std::future::Future<Output = ()>;
+    fn x(&self) -> Self::X;
+}
+
+pub struct F;
+
+impl Foo for F {
+    type X = impl std::future::Future<Output = ()>;
+    fn x(&self) -> Self::X {
+        async {}
+    }
+}
diff --git a/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs b/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
new file mode 100644
index 00000000000..2700f2370ee
--- /dev/null
+++ b/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
@@ -0,0 +1,14 @@
+// Regression test for ICE #73061
+
+// aux-build:issue-73061.rs
+
+extern crate issue_73061;
+
+pub struct Z;
+
+impl issue_73061::Foo for Z {
+    type X = <issue_73061::F as issue_73061::Foo>::X;
+    fn x(&self) -> Self::X {
+        issue_73061::F.x()
+    }
+}
diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs
index 8b396f23efd..8b5c5219430 100644
--- a/src/test/ui/associated-type-bounds/duplicate.rs
+++ b/src/test/ui/associated-type-bounds/duplicate.rs
@@ -108,18 +108,12 @@ type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
 type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr
index 71f6e4ff8b6..712211e60cb 100644
--- a/src/test/ui/associated-type-bounds/duplicate.stderr
+++ b/src/test/ui/associated-type-bounds/duplicate.stderr
@@ -224,30 +224,6 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:62:42
-   |
-LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() }
-   |                              ----------  ^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:64:42
-   |
-LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() }
-   |                              ----------  ^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:66:45
-   |
-LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() }
-   |                              -------------  ^^^^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
   --> $DIR/duplicate.rs:75:39
    |
 LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
@@ -367,12 +343,6 @@ LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                |
    |                                `Item` bound here first
 
-error: could not find defining uses
-  --> $DIR/duplicate.rs:108:1
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
   --> $DIR/duplicate.rs:108:36
    |
@@ -381,14 +351,38 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        |
    |                        `Item` bound here first
 
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:62:42
+   |
+LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() }
+   |                              ----------  ^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:64:42
+   |
+LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() }
+   |                              ----------  ^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:66:45
+   |
+LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() }
+   |                              -------------  ^^^^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
 error: could not find defining uses
-  --> $DIR/duplicate.rs:113:1
+  --> $DIR/duplicate.rs:108:51
    |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
+   |                                                   ^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:113:36
+  --> $DIR/duplicate.rs:111:36
    |
 LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -396,13 +390,13 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:118:1
+  --> $DIR/duplicate.rs:111:51
    |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
+   |                                                   ^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:118:39
+  --> $DIR/duplicate.rs:114:39
    |
 LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -410,13 +404,19 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:123:1
+  --> $DIR/duplicate.rs:114:57
+   |
+LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
+   |                                                         ^^^^^^^^^
+
+error: could not find defining uses
+  --> $DIR/duplicate.rs:117:14
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:123:40
+  --> $DIR/duplicate.rs:117:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -424,13 +424,13 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:1
+  --> $DIR/duplicate.rs:122:14
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:128:40
+  --> $DIR/duplicate.rs:122:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -438,13 +438,13 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:1
+  --> $DIR/duplicate.rs:127:14
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:133:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -452,7 +452,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:139:36
+  --> $DIR/duplicate.rs:133:36
    |
 LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -460,7 +460,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:141:36
+  --> $DIR/duplicate.rs:135:36
    |
 LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -468,7 +468,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:39
+  --> $DIR/duplicate.rs:137:39
    |
 LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -476,7 +476,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:145:34
+  --> $DIR/duplicate.rs:139:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -484,7 +484,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:147:34
+  --> $DIR/duplicate.rs:141:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -492,7 +492,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:149:37
+  --> $DIR/duplicate.rs:143:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -500,7 +500,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:151:45
+  --> $DIR/duplicate.rs:145:45
    |
 LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -508,7 +508,7 @@ LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:153:45
+  --> $DIR/duplicate.rs:147:45
    |
 LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -516,7 +516,7 @@ LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:155:48
+  --> $DIR/duplicate.rs:149:48
    |
 LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -524,7 +524,7 @@ LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:46
+  --> $DIR/duplicate.rs:151:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -532,7 +532,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:46
+  --> $DIR/duplicate.rs:151:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -540,7 +540,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:154:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -548,7 +548,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:154:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -556,7 +556,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:163:49
+  --> $DIR/duplicate.rs:157:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -564,7 +564,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:163:49
+  --> $DIR/duplicate.rs:157:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -572,7 +572,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:166:43
+  --> $DIR/duplicate.rs:160:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -580,7 +580,7 @@ LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:168:43
+  --> $DIR/duplicate.rs:162:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -588,7 +588,7 @@ LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:170:46
+  --> $DIR/duplicate.rs:164:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -596,7 +596,7 @@ LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:173:40
+  --> $DIR/duplicate.rs:167:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -604,7 +604,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:177:44
+  --> $DIR/duplicate.rs:171:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -612,7 +612,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:181:43
+  --> $DIR/duplicate.rs:175:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -620,113 +620,77 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:108:24
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   |                        ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:108:36
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   |                                    ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:113:24
-   |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   |                        ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:113:36
-   |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   |                                    ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:118:24
-   |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   |                        ^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:118:39
-   |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   |                                       ^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:123:28
+  --> $DIR/duplicate.rs:117:28
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:123:40
+  --> $DIR/duplicate.rs:117:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:28
+  --> $DIR/duplicate.rs:122:28
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:40
+  --> $DIR/duplicate.rs:122:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:28
+  --> $DIR/duplicate.rs:127:28
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:173:28
+  --> $DIR/duplicate.rs:167:28
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:173:40
+  --> $DIR/duplicate.rs:167:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:177:32
+  --> $DIR/duplicate.rs:171:32
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:177:44
+  --> $DIR/duplicate.rs:171:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:181:28
+  --> $DIR/duplicate.rs:175:28
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:181:43
+  --> $DIR/duplicate.rs:175:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
-error: aborting due to 96 previous errors; 1 warning emitted
+error: aborting due to 90 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0719`.
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 6088331cded..3b6c9791722 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
@@ -9,10 +9,14 @@ trait Bar {
 
 impl Bar for () {
     type Baa = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
-    fn define() -> Self::Baa { 0 }
+    fn define() -> Self::Baa {
+        0
+    }
 }
 
-fn define() -> Foo { 0 }
+fn define() -> Foo {
+    0
+}
 
 trait TraitWithDefault {
     type Assoc = impl Debug;
@@ -26,20 +30,20 @@ type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>
 //~| ERROR `impl Trait` in type aliases is unstable
 //~| ERROR `impl Trait` in type aliases is unstable
 //~| ERROR `impl Trait` in type aliases is unstable
-//~| ERROR `impl Trait` not allowed outside of function
-//~| ERROR `impl Trait` not allowed outside of function
-//~| ERROR `impl Trait` not allowed outside of function
+
+fn define_multiple() -> NestedFree {
+    (vec![true], 0u8, 0i32..1)
+}
 
 impl Bar for u8 {
-    type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+    type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
     //~^ ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
-    //~| ERROR `impl Trait` not allowed outside of function
-    //~| ERROR `impl Trait` not allowed outside of function
-    //~| ERROR `impl Trait` not allowed outside of function
-    fn define() -> Self::Baa { (vec![true], 0u8, 0i32..1) }
+    fn define() -> Self::Baa {
+        (vec![true], 0u8, 0i32..1)
+    }
 }
 
 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
index 55cd2984ab6..8bab0d0c4a9 100644
--- 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
@@ -17,7 +17,7 @@ LL |     type Baa = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: associated type defaults are unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:5
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:5
    |
 LL |     type Assoc = impl Debug;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     type Assoc = impl Debug;
    = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:18
    |
 LL |     type Assoc = impl Debug;
    |                  ^^^^^^^^^^
@@ -35,7 +35,7 @@ LL |     type Assoc = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:24
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                        ^^^^^^^^^^
@@ -44,7 +44,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:37
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:37
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                     ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:49
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:49
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:70
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:70
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                                                      ^^^^^^^^^^
@@ -71,84 +71,48 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:21
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:21
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                     ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:34
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:34
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                                  ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:46
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:46
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:67
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:67
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                                                                   ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:18
    |
 LL |     type Assoc = impl Debug;
    |                  ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                        ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:37
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                     ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:49
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:21
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                     ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:34
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                  ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:46
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 19 previous errors
+error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0562, E0658.
 For more information about an error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
index c7675781208..cf2773f4ef5 100644
--- a/src/test/ui/impl-trait/auto-trait.rs
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -2,22 +2,24 @@
 // the purposes of coherence checking
 #![feature(type_alias_impl_trait)]
 
-trait OpaqueTrait { }
-impl<T> OpaqueTrait for T { }
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
-fn mk_opaque() -> OpaqueType { () }
+fn mk_opaque() -> OpaqueType {
+    ()
+}
 
 #[derive(Debug)]
 struct D<T>(T);
 
-trait AnotherTrait { }
-impl<T: Send> AnotherTrait for T { }
+trait AnotherTrait {}
+impl<T: Send> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Send`.
 // (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<OpaqueType>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 5e72ca7a47b..16fe1b56b50 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<OpaqueType>`:
-  --> $DIR/auto-trait.rs:19:1
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`:
+  --> $DIR/auto-trait.rs:21:1
    |
-LL | impl<T: Send> AnotherTrait for T { }
+LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr
index 6cb2c9fb892..5131509cdf0 100644
--- a/src/test/ui/impl-trait/issue-55872-1.stderr
+++ b/src/test/ui/impl-trait/issue-55872-1.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:5
+  --> $DIR/issue-55872-1.rs:12:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
+   |              ^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
    = note: the return type of a function must have a statically known size
@@ -12,10 +12,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
    |                 ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:5
+  --> $DIR/issue-55872-1.rs:12:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
+   |              ^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr
index 01371b4d5c6..649109e4c93 100644
--- a/src/test/ui/impl-trait/issue-55872-2.stderr
+++ b/src/test/ui/impl-trait/issue-55872-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `impl std::future::Future: std::marker::Copy` is not satisfied
-  --> $DIR/issue-55872-2.rs:13:5
+  --> $DIR/issue-55872-2.rs:13:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future`
+   |              ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs
index 50cf0c8c6d6..2ef86f03d34 100644
--- a/src/test/ui/impl-trait/issue-60473.rs
+++ b/src/test/ui/impl-trait/issue-60473.rs
@@ -5,13 +5,11 @@
 
 struct A<'a>(&'a ());
 
-trait Trait<T> {
-}
+trait Trait<T> {}
 
-impl<T> Trait<T> for () {
-}
+impl<T> Trait<T> for () {}
 
 fn main() {
-    let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
-    //~^ ERROR: opaque type expands to a recursive type
+    let x: impl Trait<A> = ();
+    //~^ ERROR: missing lifetime specifier
 }
diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr
index 2d95be4e52c..367b5db5d2d 100644
--- a/src/test/ui/impl-trait/issue-60473.stderr
+++ b/src/test/ui/impl-trait/issue-60473.stderr
@@ -1,11 +1,15 @@
-error[E0720]: opaque type expands to a recursive type
-  --> $DIR/issue-60473.rs:15:12
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-60473.rs:13:23
    |
-LL |     let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
-   |            ^^^^^^^^^^^^^ expands to a recursive type
+LL |     let x: impl Trait<A> = ();
+   |                       ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn main<'a>() {
+LL |     let x: impl Trait<A<'a>> = ();
    |
-   = note: type resolves to itself
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs
index de7433a9bfc..efa67558bd7 100644
--- a/src/test/ui/impl-trait/issue-67166.rs
+++ b/src/test/ui/impl-trait/issue-67166.rs
@@ -4,8 +4,8 @@
 #![allow(incomplete_features)]
 
 pub fn run() {
-    let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
-    //~^ ERROR: opaque type expands to a recursive type
+    let _foo: Box<impl Copy + '_> = Box::new(());
+    //~^ ERROR: missing lifetime specifier
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr
index 56cba3cff0b..14c78684e3e 100644
--- a/src/test/ui/impl-trait/issue-67166.stderr
+++ b/src/test/ui/impl-trait/issue-67166.stderr
@@ -1,11 +1,15 @@
-error[E0720]: opaque type expands to a recursive type
-  --> $DIR/issue-67166.rs:7:19
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-67166.rs:7:31
    |
-LL |     let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
-   |                   ^^^^^^^^^^^^^^ expands to a recursive type
+LL |     let _foo: Box<impl Copy + '_> = Box::new(());
+   |                               ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn run<'a>() {
+LL |     let _foo: Box<impl Copy + 'a> = Box::new(());
    |
-   = note: type resolves to itself
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
index 4977f9bdbac..d173fe83fb7 100644
--- a/src/test/ui/impl-trait/negative-reasoning.rs
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -2,21 +2,22 @@
 // other trait
 #![feature(type_alias_impl_trait)]
 
-trait OpaqueTrait { }
-impl<T> OpaqueTrait for T { }
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
-fn mk_opaque() -> OpaqueType { () }
+fn mk_opaque() -> OpaqueType {
+    ()
+}
 
 #[derive(Debug)]
 struct D<T>(T);
 
-trait AnotherTrait { }
-impl<T: std::fmt::Debug> AnotherTrait for T { }
-
+trait AnotherTrait {}
+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<OpaqueType>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index 526a664726a..e43d8c857b2 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<OpaqueType>`:
-  --> $DIR/negative-reasoning.rs:18:1
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`:
+  --> $DIR/negative-reasoning.rs:19:1
    |
-LL | impl<T: std::fmt::Debug> AnotherTrait for T { }
+LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
    |
-   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
+   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `impl OpaqueTrait` in future versions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
index 5d9ae6a0301..7addc006e19 100644
--- a/src/test/ui/impl-trait/where-allowed.stderr
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -256,16 +256,16 @@ LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/where-allowed.rs:155:1
+  --> $DIR/where-allowed.rs:119:16
    |
-LL | type InTypeAlias<R> = impl Debug;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     type Out = impl Debug;
+   |                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/where-allowed.rs:119:5
+  --> $DIR/where-allowed.rs:155:23
    |
-LL |     type Out = impl Debug;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL | type InTypeAlias<R> = impl Debug;
+   |                       ^^^^^^^^^^
 
 error: aborting due to 42 previous errors
 
diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout
index 5a4b49cfa1e..cebe834824a 100644
--- a/src/test/ui/issues/issue-60662.stdout
+++ b/src/test/ui/issues/issue-60662.stdout
@@ -10,5 +10,5 @@ extern crate std;
 trait Animal { }
 
 fn main() {
-              pub type ServeFut = impl Animal;
+              pub type ServeFut = /*impl Trait*/;
           }
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 15aaf8961b7..ae04612a4dd 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
@@ -62,10 +62,10 @@ LL |     type U = impl Trait;
    |     -------------------- not a function or closure
 
 error: could not find defining uses
-  --> $DIR/inline-trait-and-foreign-items.rs:26:5
+  --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
 LL |     type U = impl Trait;
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
index 25d5f8ec68a..3cbc084ecae 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -1,5 +1,4 @@
 #![feature(type_alias_impl_trait)]
-
 #![deny(improper_ctypes)]
 
 type A = impl Fn();
@@ -10,7 +9,7 @@ pub fn ret_closure() -> A {
 
 extern "C" {
     pub fn a(_: A);
-    //~^ ERROR `extern` block uses type `A`, which is not FFI-safe
+//~^ ERROR `extern` block uses type `impl std::ops::Fn<()>`, which is not FFI-safe
 }
 
 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 712095e3208..06dfb7b8fbe 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -1,11 +1,11 @@
-error: `extern` block uses type `A`, which is not FFI-safe
-  --> $DIR/opaque-ty-ffi-unsafe.rs:12:17
+error: `extern` block uses type `impl std::ops::Fn<()>`, which is not FFI-safe
+  --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
    |
 LL |     pub fn a(_: A);
    |                 ^ not FFI-safe
    |
 note: the lint level is defined here
-  --> $DIR/opaque-ty-ffi-unsafe.rs:3:9
+  --> $DIR/opaque-ty-ffi-unsafe.rs:2:9
    |
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index 62faae1f399..cd7c37cb04b 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -9,7 +9,9 @@ mod m {
     trait PrivTr {}
     impl PrivTr for Priv {}
     pub trait PubTrAux1<T> {}
-    pub trait PubTrAux2 { type A; }
+    pub trait PubTrAux2 {
+        type A;
+    }
     impl<T> PubTrAux1<T> for u8 {}
     impl PubTrAux2 for u8 {
         type A = Priv;
@@ -41,8 +43,9 @@ mod m {
 
         type Exist = impl PrivTr;
         //~^ ERROR private trait `m::PrivTr` in public interface
-        //~| ERROR private trait `m::PrivTr` in public interface
-        fn infer_exist() -> Self::Exist { Priv }
+        fn infer_exist() -> Self::Exist {
+            Priv
+        }
     }
 }
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index dd2ea7481f3..1a3ca3f16ed 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -1,5 +1,5 @@
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:15:9
+  --> $DIR/private-in-public-assoc-ty.rs:17:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -8,7 +8,7 @@ LL |         type A = Priv;
    |         ^^^^^^^^^^^^^^ can't leak private type
 
 warning: private trait `m::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -24,7 +24,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -39,7 +39,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -54,7 +54,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:32:9
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -63,7 +63,7 @@ LL |         type Alias4 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:39:9
+  --> $DIR/private-in-public-assoc-ty.rs:41:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -72,7 +72,7 @@ LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:42:9
+  --> $DIR/private-in-public-assoc-ty.rs:44:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -80,16 +80,7 @@ LL |     trait PrivTr {}
 LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:42:9
-   |
-LL |     trait PrivTr {}
-   |     - `m::PrivTr` declared as private
-...
-LL |         type Exist = impl PrivTr;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
-
-error: aborting due to 5 previous errors; 3 warnings emitted
+error: aborting due to 4 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0445, E0446.
 For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr
index 2c5bbd7782b..3af6d0a3e07 100644
--- a/src/test/ui/save-analysis/issue-68621.stderr
+++ b/src/test/ui/save-analysis/issue-68621.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/issue-68621.rs:14:5
+  --> $DIR/issue-68621.rs:14:19
    |
 LL |     type Future = impl Trait;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^
 
 error: aborting due to previous error
 
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 b871f79aa1d..9ebf63468e7 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[E0277]: the trait bound `T: TraitWithAssoc` is not satisfied
-  --> $DIR/bound_reduction2.rs:10:1
+  --> $DIR/bound_reduction2.rs:10:15
    |
 LL | type Foo<V> = impl Trait<V>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T`
+   |               ^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T`
    |
 help: consider further restricting this bound
    |
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 ae0fee4333b..21c2e8a9db6 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,8 @@
 error: could not find defining uses
-  --> $DIR/declared_but_never_defined.rs:6:1
+  --> $DIR/declared_but_never_defined.rs:6:12
    |
 LL | type Bar = impl std::fmt::Debug;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
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 0642407aba3..c0cb94b15d0 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,8 @@
 error: could not find defining uses
-  --> $DIR/declared_but_not_defined_in_scope.rs:7:5
+  --> $DIR/declared_but_not_defined_in_scope.rs:7:20
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
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 9549074d4bf..76654d7a718 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
@@ -13,10 +13,10 @@ LL |     let z: i32 = x;
    |            expected due to this
 ...
 LL | type WrongGeneric<T> = impl 'static;
-   | ------------------------------------ the found opaque type
+   |                        ------------ the found opaque type
    |
    = note:     expected type `i32`
-           found opaque type `WrongGeneric::<&{integer}>`
+           found opaque type `impl Sized`
 
 error: aborting due to 2 previous errors
 
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 e2540e424cb..18d8daa05e6 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
@@ -13,16 +13,16 @@ LL |     let z: i32 = x;
    |            expected due to this
 ...
 LL | type WrongGeneric<T> = impl 'static;
-   | ------------------------------------ the found opaque type
+   |                        ------------ the found opaque type
    |
    = note:     expected type `i32`
-           found opaque type `WrongGeneric::<&{integer}>`
+           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:9:1
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
    |
 LL | type WrongGeneric<T> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                        ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 ...
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
index f7a04263259..911f592f73f 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
@@ -5,10 +5,10 @@ LL | type Underconstrained<T: Trait> = impl 'static;
    |                                   ^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/generic_underconstrained.rs:6:1
+  --> $DIR/generic_underconstrained.rs:6:35
    |
 LL | type Underconstrained<T: Trait> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |                                   ^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
    |
    = note: the return type of a function must have a statically known size
 help: consider restricting type parameter `T`
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index ad160abcbd5..247d68ef2a1 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -11,10 +11,10 @@ LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
    |                                              ^^^^^^^^^^^^
 
 error[E0277]: `U` doesn't implement `std::fmt::Debug`
-  --> $DIR/generic_underconstrained2.rs:5:1
+  --> $DIR/generic_underconstrained2.rs:5:45
    |
 LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                             ^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
 ...
 LL |     5u32
    |     ---- this returned value is of type `u32`
@@ -27,10 +27,10 @@ LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0277]: `V` doesn't implement `std::fmt::Debug`
-  --> $DIR/generic_underconstrained2.rs:14:1
+  --> $DIR/generic_underconstrained2.rs:14:46
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                              ^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
 ...
 LL |     5u32
    |     ---- this returned value is of type `u32`
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
new file mode 100644
index 00000000000..bc6543a9229
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
@@ -0,0 +1,18 @@
+// Ensure that we don't ICE if associated type impl trait is used in an impl
+// with an unconstrained type parameter.
+
+#![feature(type_alias_impl_trait)]
+
+trait X {
+    type I;
+    fn f() -> Self::I;
+}
+
+impl<T> X for () {
+    type I = impl Sized;
+    //~^ ERROR could not find defining uses
+    fn f() -> Self::I {}
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
new file mode 100644
index 00000000000..e8b677113db
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/impl-with-unconstrained-param.rs:14:23
+   |
+LL |     fn f() -> Self::I {}
+   |                       ^^ cannot infer type for type parameter `T`
+
+error: could not find defining uses
+  --> $DIR/impl-with-unconstrained-param.rs:12:14
+   |
+LL |     type I = impl Sized;
+   |              ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs b/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
new file mode 100644
index 00000000000..3a7a5da075f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
@@ -0,0 +1,24 @@
+// Regression test for #57188
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Baz<'a> {
+    source: &'a str,
+}
+
+trait Foo<'a> {
+    type T: Iterator<Item = Baz<'a>> + 'a;
+    fn foo(source: &'a str) -> Self::T;
+}
+
+struct Bar;
+impl<'a> Foo<'a> for Bar {
+    type T = impl Iterator<Item = Baz<'a>> + 'a;
+    fn foo(source: &'a str) -> Self::T {
+        std::iter::once(Baz { source })
+    }
+}
+
+fn main() {}
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 f648b7bfc99..cc121ac89fb 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[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-57611-trait-alias.rs:17:5
+  --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _`
+   |                ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _`
 ...
 LL |         |x| x
    |         ----- found signature of `fn(_) -> _`
@@ -10,10 +10,10 @@ LL |         |x| x
    = note: the return type of a function must have a statically known size
 
 error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X`
-  --> $DIR/issue-57611-trait-alias.rs:17:5
+  --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
+   |                ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
    |
    = note: the return type of a function must have a statically known size
 
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 2796c77baa1..bf2d612fcdb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -8,20 +8,20 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `(): Bug` is not satisfied
-  --> $DIR/issue-60371.rs:8:5
+  --> $DIR/issue-60371.rs:8:17
    |
 LL |     type Item = impl Bug;
-   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Bug` is not implemented for `()`
+   |                 ^^^^^^^^ the trait `Bug` is not implemented for `()`
    |
    = help: the following implementations were found:
              <&() as Bug>
    = note: the return type of a function must have a statically known size
 
 error: could not find defining uses
-  --> $DIR/issue-60371.rs:8:5
+  --> $DIR/issue-60371.rs:8:17
    |
 LL |     type Item = impl Bug;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^
 
 error: aborting due to 3 previous errors
 
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 4eb7f7836d8..78def0d1136 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -17,11 +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
-    //~| 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
+        (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
     }
 }
 
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 55984609437..66fa862ef9d 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -4,23 +4,11 @@ error: non-defining opaque type use in defining scope
 LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
    |                                  ^^^^^^^^^^^^^^
    |
-note: used non-generic type `_` for generic parameter
-  --> $DIR/issue-60564.rs:8:22
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                      ^
-
-error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:19:34
-   |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^
-   |
 note: used non-generic type `u8` for generic parameter
   --> $DIR/issue-60564.rs:8:25
    |
 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-62000-associate-impl-trait-lifetimes.rs b/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs
new file mode 100644
index 00000000000..36779a0ce89
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs
@@ -0,0 +1,38 @@
+// Regression test for #62988
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait MyTrait {
+    type AssocType: Send;
+    fn ret(&self) -> Self::AssocType;
+}
+
+impl MyTrait for () {
+    type AssocType = impl Send;
+    fn ret(&self) -> Self::AssocType {
+        ()
+    }
+}
+
+impl<'a> MyTrait for &'a () {
+    type AssocType = impl Send;
+    fn ret(&self) -> Self::AssocType {
+        ()
+    }
+}
+
+trait MyLifetimeTrait<'a> {
+    type AssocType: Send + 'a;
+    fn ret(&self) -> Self::AssocType;
+}
+
+impl<'a> MyLifetimeTrait<'a> for &'a () {
+    type AssocType = impl Send + 'a;
+    fn ret(&self) -> Self::AssocType {
+        *self
+    }
+}
+
+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 bef4d01093c..d07f64c3312 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,10 +1,10 @@
 error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:8:5: 8:28] as std::ops::FnOnce<()>>::Output == ()`
-  --> $DIR/issue-63279.rs:5:1
+  --> $DIR/issue-63279.rs:5:16
    |
 LL | type Closure = impl FnOnce();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `()`
+   |                ^^^^^^^^^^^^^ expected opaque type, found `()`
    |
-   = note: expected opaque type `Closure`
+   = note: expected opaque type `impl std::ops::FnOnce<()>`
                 found unit type `()`
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
new file mode 100644
index 00000000000..6732902c09a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
@@ -0,0 +1,22 @@
+// Regression test for #69136
+
+#![feature(type_alias_impl_trait)]
+
+trait SomeTrait {}
+
+impl SomeTrait for () {}
+
+trait WithAssoc<A> {
+    type AssocType;
+}
+
+impl<T> WithAssoc<T> for () {
+    type AssocType = ();
+}
+
+type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+//~^ ERROR use of undeclared lifetime name `'a`
+
+fn my_fun() -> Return<()> {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
new file mode 100644
index 00000000000..fe45e39d938
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
@@ -0,0 +1,11 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
+   |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |             -                                                   ^^ undeclared lifetime
+   |             |
+   |             help: consider introducing lifetime `'a` here: `'a,`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
new file mode 100644
index 00000000000..a6916eda8b0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
@@ -0,0 +1,23 @@
+// Test-pass variant of #69136
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait SomeTrait {}
+
+impl SomeTrait for () {}
+
+trait WithAssoc {
+    type AssocType;
+}
+
+impl WithAssoc for () {
+    type AssocType = ();
+}
+
+type Return<'a> = impl WithAssoc<AssocType = impl Sized + 'a>;
+
+fn my_fun<'a>() -> Return<'a> {}
+
+fn main() {}
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
index 70c99c944d6..4fbbf347528 100644
--- 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
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/never_reveal_concrete_type.rs:13:27
    |
 LL | type NoReveal = impl std::fmt::Debug;
-   | ------------------------------------- the found opaque type
+   |                 -------------------- the found opaque type
 ...
 LL |     let _: &'static str = x;
    |            ------------   ^ expected `&str`, found opaque type
@@ -10,9 +10,9 @@ LL |     let _: &'static str = x;
    |            expected due to this
    |
    = note: expected reference `&'static str`
-            found opaque type `NoReveal`
+            found opaque type `impl std::fmt::Debug`
 
-error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
+error[E0605]: non-primitive cast: `impl std::fmt::Debug` as `&'static str`
   --> $DIR/never_reveal_concrete_type.rs:14:13
    |
 LL |     let _ = x as &'static str;
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 444e6e8214f..61025e84692 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,8 @@
 error: could not find defining uses
-  --> $DIR/no_inferrable_concrete_type.rs:6:1
+  --> $DIR/no_inferrable_concrete_type.rs:6:12
    |
 LL | type Foo = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^
 
 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 375c0bc7fe2..d237cc6238a 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
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:15:19
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     -------------------------------------- the found opaque type
+   |                    ---------------------- the found opaque type
 ...
 LL |     let _: &str = bomp();
    |            ----   ^^^^^^ expected `&str`, found opaque type
@@ -10,20 +10,20 @@ LL |     let _: &str = bomp();
    |            expected due to this
    |
    = note: expected reference `&str`
-            found opaque type `Boo`
+            found opaque type `impl std::fmt::Debug`
 
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     -------------------------------------- the expected opaque type
+   |                    ---------------------- the expected opaque type
 ...
 LL | fn bomp() -> boo::Boo {
-   |              -------- expected `Boo` because of return type
+   |              -------- expected `impl std::fmt::Debug` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `Boo`
+   = note: expected opaque type `impl std::fmt::Debug`
                 found reference `&'static str`
 
 error: aborting due to 2 previous errors
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 02ab3399ea6..726f4ea6e00 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,8 @@
 error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:1
+  --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12
    |
 LL | type Foo = impl Fn() -> Foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
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 e9abb795886..3947cc4d270 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,8 @@
 error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:1
+  --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12
    |
 LL | type Foo = impl Bar<Foo, Item = Foo>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
new file mode 100644
index 00000000000..fd954801dc0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(type_alias_impl_trait)]
+
+use std::iter::{once, Chain};
+
+type I<A> = Chain<A, impl Iterator<Item = &'static str>>;
+fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> {
+    x.chain(once("5"))
+}
+
+fn main() {
+    assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::<Vec<_>>());
+}
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index d80ad47ab24..318d0b69d57 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -379,7 +379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
             TyKind::Path(ref path) => {
                 self.collect_anonymous_lifetimes(path, ty);
             },
-            TyKind::Def(item, _) => {
+            TyKind::OpaqueDef(item, _) => {
                 let map = self.cx.tcx.hir();
                 if let ItemKind::OpaqueTy(ref exist_ty) = map.expect_item(item.id).kind {
                     for bound in exist_ty.bounds {
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index cb72a240582..03ab274d9ca 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn {
 
 fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
     if_chain! {
-        if let TyKind::Def(item_id, _) = ty.kind;
+        if let TyKind::OpaqueDef(item_id, _) = ty.kind;
         let item = cx.tcx.hir().item(item_id.id);
         if let ItemKind::OpaqueTy(opaque) = &item.kind;
         if opaque.bounds.len() == 1;
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 2eefb6bbaf4..0fd1e87f9e4 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -187,7 +187,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             hir::ImplItemKind::Const(..) => "an associated constant",
             hir::ImplItemKind::Fn(..) => "a method",
             hir::ImplItemKind::TyAlias(_) => "an associated type",
-            hir::ImplItemKind::OpaqueTy(_) => "an existential type",
         };
         self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
     }
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 3ad3d5aee4d..1802470b184 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
 
         let desc = match impl_item.kind {
             hir::ImplItemKind::Fn(..) => "a method",
-            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return,
+            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) => return,
         };
 
         let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index 473a730dad5..7a84f1c986a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -710,7 +710,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     segment.ident.name.hash(&mut self.s);
                 },
             },
-            TyKind::Def(_, arg_list) => {
+            TyKind::OpaqueDef(_, arg_list) => {
                 for arg in *arg_list {
                     match arg {
                         GenericArg::Lifetime(ref l) => self.hash_lifetime(l),
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 649b166e98e..afde971f9df 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -63,7 +63,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector {
             },
             hir::ImplItemKind::Fn(..) => println!("method"),
             hir::ImplItemKind::TyAlias(_) => println!("associated type"),
-            hir::ImplItemKind::OpaqueTy(_) => println!("existential type"),
         }
     }
     // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx