about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs124
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs134
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs40
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs55
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/context.rs1
-rw-r--r--compiler/rustc_middle/src/ty/error.rs1
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs1
-rw-r--r--compiler/rustc_privacy/src/lib.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/weak_types.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs5
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs1
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs34
-rw-r--r--compiler/rustc_type_ir/src/sty.rs8
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs1
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed6
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs6
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.rs6
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.stderr33
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.rs22
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.stderr18
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs26
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr9
-rw-r--r--tests/ui/impl-trait/nested-return-type2-tait.stderr4
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait.stderr4
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait2.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs3
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr15
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr5
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs3
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr15
-rw-r--r--tests/ui/lint/lint-ctypes-73249-2.rs8
-rw-r--r--tests/ui/lint/lint-ctypes-73249-2.stderr6
-rw-r--r--tests/ui/lint/lint-ctypes-73251-1.rs6
-rw-r--r--tests/ui/lint/lint-ctypes-73251-1.stderr6
-rw-r--r--tests/ui/lint/lint-ctypes-73251-2.rs2
-rw-r--r--tests/ui/lint/lint-ctypes-73251-2.stderr6
-rw-r--r--tests/ui/lint/lint-ctypes-73251.rs4
-rw-r--r--tests/ui/lint/opaque-ty-ffi-unsafe.rs4
-rw-r--r--tests/ui/lint/opaque-ty-ffi-unsafe.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked3.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/bounds.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/defining-use-submodule.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs14
-rw-r--r--tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/obligation_ice.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/privacy.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/privacy.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr5
87 files changed, 625 insertions, 344 deletions
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 11ad5b49df2..4f01e0a24a5 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -63,6 +63,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
+            ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"),
             ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
new file mode 100644
index 00000000000..05a3ab63d5c
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -0,0 +1,124 @@
+use rustc_ast::TraitObjectSyntax;
+use rustc_errors::{Diagnostic, StashKey};
+use rustc_hir as hir;
+use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
+use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
+
+use super::AstConv;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    /// Make sure that we are in the condition to suggest the blanket implementation.
+    pub(super) fn maybe_lint_blanket_trait_impl(
+        &self,
+        self_ty: &hir::Ty<'_>,
+        diag: &mut Diagnostic,
+    ) {
+        let tcx = self.tcx();
+        let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
+        if let hir::Node::Item(hir::Item {
+            kind:
+                hir::ItemKind::Impl(hir::Impl {
+                    self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, ..
+                }),
+            ..
+        }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
+        {
+            if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
+                return;
+            }
+            let of_trait_span = of_trait_ref.path.span;
+            // make sure that we are not calling unwrap to abort during the compilation
+            let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; };
+            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; };
+            // check if the trait has generics, to make a correct suggestion
+            let param_name = generics.params.next_type_param_name(None);
+
+            let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
+                (span, format!(", {}: {}", param_name, impl_trait_name))
+            } else {
+                (generics.span, format!("<{}: {}>", param_name, impl_trait_name))
+            };
+            diag.multipart_suggestion(
+            format!("alternatively use a blanket \
+                     implementation to implement `{of_trait_name}` for \
+                     all types that also implement `{impl_trait_name}`"),
+                vec![
+                    (self_ty.span, param_name),
+                    add_generic_sugg,
+                ],
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
+    pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
+        let tcx = self.tcx();
+        if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
+            self_ty.kind
+        {
+            let needs_bracket = in_path
+                && !tcx
+                    .sess
+                    .source_map()
+                    .span_to_prev_source(self_ty.span)
+                    .ok()
+                    .is_some_and(|s| s.trim_end().ends_with('<'));
+
+            let is_global = poly_trait_ref.trait_ref.path.is_global();
+
+            let mut sugg = Vec::from_iter([(
+                self_ty.span.shrink_to_lo(),
+                format!(
+                    "{}dyn {}",
+                    if needs_bracket { "<" } else { "" },
+                    if is_global { "(" } else { "" },
+                ),
+            )]);
+
+            if is_global || needs_bracket {
+                sugg.push((
+                    self_ty.span.shrink_to_hi(),
+                    format!(
+                        "{}{}",
+                        if is_global { ")" } else { "" },
+                        if needs_bracket { ">" } else { "" },
+                    ),
+                ));
+            }
+
+            if self_ty.span.edition().rust_2021() {
+                let msg = "trait objects must include the `dyn` keyword";
+                let label = "add `dyn` keyword before this trait";
+                let mut diag =
+                    rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg);
+                if self_ty.span.can_be_used_for_suggestions() {
+                    diag.multipart_suggestion_verbose(
+                        label,
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+                // check if the impl trait that we are considering is a impl of a local trait
+                self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
+                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
+            } else {
+                let msg = "trait objects without an explicit `dyn` are deprecated";
+                tcx.struct_span_lint_hir(
+                    BARE_TRAIT_OBJECTS,
+                    self_ty.hir_id,
+                    self_ty.span,
+                    msg,
+                    |lint| {
+                        lint.multipart_suggestion_verbose(
+                            "use `dyn`",
+                            sugg,
+                            Applicability::MachineApplicable,
+                        );
+                        self.maybe_lint_blanket_trait_impl(&self_ty, lint);
+                        lint
+                    },
+                );
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 1037a49acdf..221c7ce4f6f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -4,6 +4,7 @@
 
 mod errors;
 pub mod generics;
+mod lint;
 
 use crate::astconv::errors::prohibit_assoc_ty_binding;
 use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
@@ -19,7 +20,7 @@ use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
-    MultiSpan, StashKey,
+    MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -33,14 +34,12 @@ use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{DynKind, ToPredicate};
-use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
+use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use rustc_trait_selection::traits::error_reporting::{
-    report_object_safety_error, suggestions::NextTypeParamName,
-};
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{
     self, astconv_object_safety_violations, NormalizeExt, ObligationCtxt,
@@ -1458,7 +1457,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         item_segment: &hir::PathSegment<'_>,
     ) -> Ty<'tcx> {
         let substs = self.ast_path_substs_for_ty(span, did, item_segment);
-        self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
+        let ty = self.tcx().at(span).type_of(did);
+
+        if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
+            && ty.skip_binder().has_opaque_types()
+        {
+            // Type aliases referring to types that contain opaque types (but aren't just directly
+            // referencing a single opaque type) get encoded as a type alias that normalization will
+            // then actually instantiate the where bounds of.
+            let alias_ty = self.tcx().mk_alias_ty(did, substs);
+            self.tcx().mk_alias(ty::Weak, alias_ty)
+        } else {
+            ty.subst(self.tcx(), substs)
+        }
     }
 
     fn conv_object_ty_poly_trait_ref(
@@ -3703,115 +3714,4 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
         Some(r)
     }
-
-    /// Make sure that we are in the condition to suggest the blanket implementation.
-    fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) {
-        let tcx = self.tcx();
-        let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
-        if let hir::Node::Item(hir::Item {
-            kind:
-                hir::ItemKind::Impl(hir::Impl {
-                    self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, ..
-                }),
-            ..
-        }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
-        {
-            if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
-                return;
-            }
-            let of_trait_span = of_trait_ref.path.span;
-            // make sure that we are not calling unwrap to abort during the compilation
-            let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; };
-            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; };
-            // check if the trait has generics, to make a correct suggestion
-            let param_name = generics.params.next_type_param_name(None);
-
-            let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
-                (span, format!(", {}: {}", param_name, impl_trait_name))
-            } else {
-                (generics.span, format!("<{}: {}>", param_name, impl_trait_name))
-            };
-            diag.multipart_suggestion(
-            format!("alternatively use a blanket \
-                     implementation to implement `{of_trait_name}` for \
-                     all types that also implement `{impl_trait_name}`"),
-                vec![
-                    (self_ty.span, param_name),
-                    add_generic_sugg,
-                ],
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-
-    fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
-        let tcx = self.tcx();
-        if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
-            self_ty.kind
-        {
-            let needs_bracket = in_path
-                && !tcx
-                    .sess
-                    .source_map()
-                    .span_to_prev_source(self_ty.span)
-                    .ok()
-                    .is_some_and(|s| s.trim_end().ends_with('<'));
-
-            let is_global = poly_trait_ref.trait_ref.path.is_global();
-
-            let mut sugg = Vec::from_iter([(
-                self_ty.span.shrink_to_lo(),
-                format!(
-                    "{}dyn {}",
-                    if needs_bracket { "<" } else { "" },
-                    if is_global { "(" } else { "" },
-                ),
-            )]);
-
-            if is_global || needs_bracket {
-                sugg.push((
-                    self_ty.span.shrink_to_hi(),
-                    format!(
-                        "{}{}",
-                        if is_global { ")" } else { "" },
-                        if needs_bracket { ">" } else { "" },
-                    ),
-                ));
-            }
-
-            if self_ty.span.edition().rust_2021() {
-                let msg = "trait objects must include the `dyn` keyword";
-                let label = "add `dyn` keyword before this trait";
-                let mut diag =
-                    rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg);
-                if self_ty.span.can_be_used_for_suggestions() {
-                    diag.multipart_suggestion_verbose(
-                        label,
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-                // check if the impl trait that we are considering is a impl of a local trait
-                self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
-                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
-            } else {
-                let msg = "trait objects without an explicit `dyn` are deprecated";
-                tcx.struct_span_lint_hir(
-                    BARE_TRAIT_OBJECTS,
-                    self_ty.hir_id,
-                    self_ty.span,
-                    msg,
-                    |lint| {
-                        lint.multipart_suggestion_verbose(
-                            "use `dyn`",
-                            sugg,
-                            Applicability::MachineApplicable,
-                        );
-                        self.maybe_lint_blanket_trait_impl(&self_ty, lint);
-                        lint
-                    },
-                );
-            }
-        }
-    }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4554d167080..f93f395caed 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -217,10 +217,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
             check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
         }
         hir::ItemKind::Static(ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, false);
+            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
         }
         hir::ItemKind::Const(ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, false);
+            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
         }
         hir::ItemKind::Struct(_, ast_generics) => {
             check_type_defn(tcx, item, false);
@@ -242,6 +242,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
         }
         // `ForeignItem`s are handled separately.
         hir::ItemKind::ForeignMod { .. } => {}
+        hir::ItemKind::TyAlias(hir_ty, ..) => {
+            if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
+                // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
+                check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+            }
+        }
         _ => {}
     }
 }
@@ -258,7 +264,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
         hir::ForeignItemKind::Fn(decl, ..) => {
             check_item_fn(tcx, def_id, item.ident, item.span, decl)
         }
-        hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
+        hir::ForeignItemKind::Static(ty, ..) => {
+            check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
+        }
         hir::ForeignItemKind::Type => (),
     }
 }
@@ -1100,20 +1108,32 @@ fn check_item_fn(
     })
 }
 
-fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
+enum UnsizedHandling {
+    Forbid,
+    Allow,
+    AllowIfForeignTail,
+}
+
+fn check_item_type(
+    tcx: TyCtxt<'_>,
+    item_id: LocalDefId,
+    ty_span: Span,
+    unsized_handling: UnsizedHandling,
+) {
     debug!("check_item_type: {:?}", item_id);
 
     enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
         let ty = tcx.type_of(item_id).subst_identity();
         let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
 
-        let mut forbid_unsized = true;
-        if allow_foreign_ty {
-            let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
-            if let ty::Foreign(_) = tail.kind() {
-                forbid_unsized = false;
+        let forbid_unsized = match unsized_handling {
+            UnsizedHandling::Forbid => true,
+            UnsizedHandling::Allow => false,
+            UnsizedHandling::AllowIfForeignTail => {
+                let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
+                !matches!(tail.kind(), ty::Foreign(_))
             }
-        }
+        };
 
         wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
         if forbid_unsized {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 23beacd2a8c..eb299a1ea79 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -200,35 +200,32 @@ fn do_orphan_check_impl<'tcx>(
                 NonlocalImpl::DisallowOther,
             ),
 
-            // trait Id { type This: ?Sized; }
-            // impl<T: ?Sized> Id for T {
-            //     type This = T;
-            // }
-            // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
-            ty::Alias(AliasKind::Projection, _) => (
-                LocalImpl::Disallow { problematic_kind: "associated type" },
-                NonlocalImpl::DisallowOther,
-            ),
-
-            // ```
-            // struct S<T>(T);
-            // impl<T: ?Sized> S<T> {
-            //     type This = T;
-            // }
-            // impl<T: ?Sized> AutoTrait for S<T>::This {}
-            // ```
-            // FIXME(inherent_associated_types): The example code above currently leads to a cycle
-            ty::Alias(AliasKind::Inherent, _) => (
-                LocalImpl::Disallow { problematic_kind: "associated type" },
-                NonlocalImpl::DisallowOther,
-            ),
-
-            // type Opaque = impl Trait;
-            // impl AutoTrait for Opaque {}
-            ty::Alias(AliasKind::Opaque, _) => (
-                LocalImpl::Disallow { problematic_kind: "opaque type" },
-                NonlocalImpl::DisallowOther,
-            ),
+            ty::Alias(kind, _) => {
+                let problematic_kind = match kind {
+                    // trait Id { type This: ?Sized; }
+                    // impl<T: ?Sized> Id for T {
+                    //     type This = T;
+                    // }
+                    // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
+                    AliasKind::Projection => "associated type",
+                    // type Foo = (impl Sized, bool)
+                    // impl AutoTrait for Foo {}
+                    AliasKind::Weak => "type alias",
+                    // type Opaque = impl Trait;
+                    // impl AutoTrait for Opaque {}
+                    AliasKind::Opaque => "opaque type",
+                    // ```
+                    // struct S<T>(T);
+                    // impl<T: ?Sized> S<T> {
+                    //     type This = T;
+                    // }
+                    // impl<T: ?Sized> AutoTrait for S<T>::This {}
+                    // ```
+                    // FIXME(inherent_associated_types): The example code above currently leads to a cycle
+                    AliasKind::Inherent => "associated type",
+                };
+                (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
+            }
 
             ty::Bool
             | ty::Char
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index b92d561fb86..90e8e523ea3 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -122,6 +122,7 @@ pub(super) fn explicit_item_bounds(
             };
             opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
         _ => bug!("item_bounds called on {:?}", def_id),
     };
     ty::EarlyBinder::bind(bounds)
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index e4c6e6e391a..a653a652231 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>(
                 ref item => bug!("Unexpected TraitItem {:?}", item),
             },
             hir::Node::Item(item) => match item.kind {
-                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty],
+                hir::ItemKind::TyAlias(ty, _)
+                | hir::ItemKind::Static(ty, _, _)
+                | hir::ItemKind::Const(ty, _) => vec![ty],
                 hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
                     Some(t) => t
                         .path
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 3e4812e7ca9..fc1f90fdc13 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2375,6 +2375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ty::AliasKind::Projection | ty::AliasKind::Inherent => {
                     format!("the associated type `{}`", p)
                 }
+                ty::AliasKind::Weak => format!("the type alias `{}`", p),
                 ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
             },
         };
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 7b05bff5151..f02f3668dc1 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1465,8 +1465,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
         let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
             return
         };
-        if let hir::TyKind::OpaqueDef(..) = ty.kind {
-            // Bounds are respected for `type X = impl Trait`
+        if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
+            // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
             return;
         }
         if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index ec9e7c7fdae..9a2d45ccd66 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1255,7 +1255,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             }
 
             ty::Param(..)
-            | ty::Alias(ty::Projection | ty::Inherent, ..)
+            | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
             | ty::Infer(..)
             | ty::Bound(..)
             | ty::Error(_)
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a6c8d41e925..132b11b29eb 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1904,6 +1904,16 @@ rustc_queries! {
     }
 
     /// Do not call this query directly: invoke `normalize` instead.
+    query normalize_weak_ty(
+        goal: CanonicalProjectionGoal<'tcx>
+    ) -> Result<
+        &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
+        NoSolution,
+    > {
+        desc { "normalizing `{}`", goal.value.value }
+    }
+
+    /// Do not call this query directly: invoke `normalize` instead.
     query normalize_inherent_projection_ty(
         goal: CanonicalProjectionGoal<'tcx>
     ) -> Result<
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index bf3872e81d4..b63e049a520 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -448,6 +448,9 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
     ConstParam(Ty<'tcx>),
+
+    /// Obligations emitted during the normalization of a weak type alias.
+    TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
 }
 
 /// The 'location' at which we try to perform HIR-based wf checking.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 4ee543bbfb6..449129b8418 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2012,6 +2012,7 @@ impl<'tcx> TyCtxt<'tcx> {
             (ty::Opaque, DefKind::OpaqueTy)
                 | (ty::Projection | ty::Inherent, DefKind::AssocTy)
                 | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
+                | (ty::Weak, DefKind::TyAlias)
         );
         self.mk_ty_from_kind(Alias(kind, alias_ty))
     }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 66293f19eef..c794c3faded 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -300,6 +300,7 @@ impl<'tcx> Ty<'tcx> {
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
             ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
+            ty::Alias(ty::Weak, _) => "type alias".into(),
             ty::Param(_) => "type parameter".into(),
             ty::Alias(ty::Opaque, ..) => "opaque type".into(),
         }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index d64875a9f00..9cce9d64d5d 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -178,7 +178,7 @@ impl FlagComputation {
 
             &ty::Alias(kind, data) => {
                 self.add_flags(match kind {
-                    ty::Projection => TypeFlags::HAS_TY_PROJECTION,
+                    ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION,
                     ty::Inherent => TypeFlags::HAS_TY_INHERENT,
                     ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
                 });
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6156fdf7eac..f36b8ad8df6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -731,7 +731,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Alias(ty::Projection | ty::Inherent, ref data) => {
+            ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
                     && self.tcx().is_impl_trait_in_trait(data.def_id)
                 {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 8bcae3d9ab7..74a3bddf2fa 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -391,13 +391,13 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
 /// Relates `a` and `b` structurally, calling the relation for all nested values.
 /// Any semantic equality, e.g. of projections, and inference variables have to be
 /// handled by the caller.
+#[instrument(level = "trace", skip(relation), ret)]
 pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     a: Ty<'tcx>,
     b: Ty<'tcx>,
 ) -> RelateResult<'tcx, Ty<'tcx>> {
     let tcx = relation.tcx();
-    debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
     match (a.kind(), b.kind()) {
         (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
             // The caller should handle these cases!
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d19a7bcde79..5f2f241bc0d 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1231,6 +1231,7 @@ impl<'tcx> AliasTy<'tcx> {
             DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
             DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
             DefKind::OpaqueTy => ty::Opaque,
+            DefKind::TyAlias => ty::Weak,
             kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
         }
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index a51a1c9a8a4..5ef11acadce 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -242,6 +242,9 @@ where
                     }
                 }
             }
+            ty::Alias(ty::Weak, alias) => {
+                self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty);
+            }
             ty::Alias(ty::Projection, proj) => {
                 if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 0a805e2422d..5dc00e31786 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -483,6 +483,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             }
 
             ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
+            ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"),
             ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"),
         }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index e6eddf24844..543611daae8 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -510,10 +510,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::Placeholder(..)
             | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
             | ty::Alias(ty::Inherent, _)
+            | ty::Alias(ty::Weak, _)
             | ty::Error(_) => return,
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
             | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
-            // Excluding IATs here as they don't have meaningful item bounds.
+            // Excluding IATs and type aliases here as they don't have meaningful item bounds.
             ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
         };
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 0f3f8f1ac2c..97b86a06c8c 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -33,7 +33,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
         ty::Dynamic(..)
         | ty::Param(..)
         | ty::Foreign(..)
-        | ty::Alias(ty::Projection | ty::Inherent, ..)
+        | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
         | ty::Placeholder(..)
         | ty::Bound(..)
         | ty::Infer(_) => {
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index f4c29c837b8..a30a14df80b 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -29,6 +29,7 @@ mod opaques;
 mod project_goals;
 mod search_graph;
 mod trait_goals;
+mod weak_types;
 
 pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt};
 pub use fulfill::FulfillmentCtxt;
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 8303bab4c36..e9600968f48 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -57,6 +57,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             }
             DefKind::AnonConst => self.normalize_anon_const(goal),
             DefKind::OpaqueTy => self.normalize_opaque_type(goal),
+            DefKind::TyAlias => self.normalize_weak_type(goal),
             kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)),
         }
     }
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 60cf386a289..279fc1229d4 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -618,7 +618,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Alias(ty::Projection | ty::Inherent, ..)
+            | ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..)
             | ty::Placeholder(..) => Some(Err(NoSolution)),
 
             ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs
new file mode 100644
index 00000000000..b095b54c554
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs
@@ -0,0 +1,19 @@
+use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
+use rustc_middle::ty;
+
+use super::EvalCtxt;
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    pub(super) fn normalize_weak_type(
+        &mut self,
+        goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        let tcx = self.tcx();
+        let weak_ty = goal.predicate.projection_ty;
+        let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
+
+        let actual = tcx.type_of(weak_ty.def_id).subst(tcx, weak_ty.substs);
+        self.eq(goal.param_env, expected, actual)?;
+        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 3193d00e11b..0065c7fc253 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -695,7 +695,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
             | ty::RawPtr(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Alias(ty::Projection | ty::Inherent, ..) => self.found_non_local_ty(ty),
+            | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) => {
+                self.found_non_local_ty(ty)
+            }
 
             ty::Param(..) => self.found_param_ty(ty),
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1bc4599377a..ffbe2888bf8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1824,12 +1824,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ty::Alias(ty::Projection, ..) => Some(12),
                 ty::Alias(ty::Inherent, ..) => Some(13),
                 ty::Alias(ty::Opaque, ..) => Some(14),
-                ty::Never => Some(15),
-                ty::Adt(..) => Some(16),
-                ty::Generator(..) => Some(17),
-                ty::Foreign(..) => Some(18),
-                ty::GeneratorWitness(..) => Some(19),
-                ty::GeneratorWitnessMIR(..) => Some(20),
+                ty::Alias(ty::Weak, ..) => Some(15),
+                ty::Never => Some(16),
+                ty::Adt(..) => Some(17),
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::GeneratorWitnessMIR(..) => Some(21),
                 ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 5783383e93e..fcf813e3a39 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3198,6 +3198,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     )
                 });
             }
+            ObligationCauseCode::TypeAlias(ref nested, span, def_id) => {
+                // #74711: avoid a stack overflow
+                ensure_sufficient_stack(|| {
+                    self.note_obligation_cause_code(
+                        body_id,
+                        err,
+                        predicate,
+                        param_env,
+                        nested,
+                        obligated_types,
+                        seen_requirements,
+                    )
+                });
+                let mut multispan = MultiSpan::from(span);
+                multispan.push_span_label(span, "required by this bound");
+                err.span_note(
+                    multispan,
+                    format!(
+                        "required by a bound on the type alias `{}`",
+                        self.infcx.tcx.item_name(def_id)
+                    ),
+                );
+            }
             ObligationCauseCode::FunctionArgumentObligation {
                 arg_hir_id,
                 call_hir_id,
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index f8d056e321e..ff55eaf13ad 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId;
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
-type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
+pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
 pub trait InferCtxtExt<'a, 'tcx> {
     fn implied_outlives_bounds(
         &self,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0a1e971f268..8466b3fc954 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -31,6 +31,7 @@ use rustc_infer::infer::at::At;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::ImplSourceBuiltinData;
+use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
@@ -621,6 +622,30 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 );
                 normalized_ty
             }
+            ty::Weak => {
+                let infcx = self.selcx.infcx;
+                self.obligations.extend(
+                    infcx
+                        .tcx
+                        .predicates_of(data.def_id)
+                        .instantiate_own(infcx.tcx, data.substs)
+                        .map(|(mut predicate, span)| {
+                            if data.has_escaping_bound_vars() {
+                                (predicate, ..) = BoundVarReplacer::replace_bound_vars(
+                                    infcx,
+                                    &mut self.universes,
+                                    predicate,
+                                );
+                            }
+                            let mut cause = self.cause.clone();
+                            cause.map_code(|code| {
+                                ObligationCauseCode::TypeAlias(code, span, data.def_id)
+                            });
+                            Obligation::new(infcx.tcx, cause, self.param_env, predicate)
+                        }),
+                );
+                infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self)
+            }
 
             ty::Inherent if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
@@ -1545,7 +1570,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        // Excluding IATs here as they don't have meaningful item bounds.
+        // Excluding IATs and type aliases here as they don't have meaningful item bounds.
         ty::Alias(ty::Projection | ty::Opaque, ref data) => {
             tcx.item_bounds(data.def_id).subst(tcx, data.substs)
         }
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 8bf934cb78a..2d97a808225 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -257,7 +257,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
 
             ty::Opaque => ty.try_super_fold_with(self)?,
 
-            ty::Projection | ty::Inherent => {
+            ty::Projection | ty::Inherent | ty::Weak => {
                 // See note in `rustc_trait_selection::traits::project`
 
                 let infcx = self.infcx;
@@ -282,6 +282,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                 let result = match kind {
                     ty::Projection => tcx.normalize_projection_ty(c_data),
+                    ty::Weak => tcx.normalize_weak_ty(c_data),
                     ty::Inherent => tcx.normalize_inherent_projection_ty(c_data),
                     _ => unreachable!(),
                 }?;
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 3c223db5a0b..f2dfa6921f4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -143,7 +143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            // Excluding IATs here as they don't have meaningful item bounds.
+            // Excluding IATs and type aliases here as they don't have meaningful item bounds.
             ty::Alias(ty::Projection | ty::Opaque, _) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 7853af959ad..d2c2cadd617 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -163,7 +163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            // Excluding IATs here as they don't have meaningful item bounds.
+            // Excluding IATs and type aliases here as they don't have meaningful item bounds.
             ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 (def_id, substs)
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4c5a794bc81..e72d3ca97d7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2314,7 +2314,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             | ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Alias(ty::Projection | ty::Inherent, ..)
+            | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
             | ty::Bound(..)
             | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}", t);
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 086ab32b520..92d899b0f13 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -731,6 +731,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     }
                 }
 
+                ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => {
+                    let obligations = self.nominal_obligations(def_id, substs);
+                    self.out.extend(obligations);
+                }
+
                 ty::Dynamic(data, r, _) => {
                     // WfObject
                     //
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index e6c6e0f13df..f9a7c8c386a 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -372,6 +372,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
                     substitution: substs.lower_into(interner),
                 }))
             }
+            ty::Alias(ty::Weak, ty::AliasTy { .. }) => unimplemented!(),
             ty::Alias(ty::Inherent, _) => unimplemented!(),
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index b552ba41acd..83828f177bc 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -10,7 +10,12 @@ use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
 use std::sync::atomic::Ordering;
 
 pub(crate) fn provide(p: &mut Providers) {
-    *p = Providers { normalize_projection_ty, normalize_inherent_projection_ty, ..*p };
+    *p = Providers {
+        normalize_projection_ty,
+        normalize_weak_ty,
+        normalize_inherent_projection_ty,
+        ..*p
+    };
 }
 
 fn normalize_projection_ty<'tcx>(
@@ -43,6 +48,33 @@ fn normalize_projection_ty<'tcx>(
     )
 }
 
+fn normalize_weak_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    goal: CanonicalProjectionGoal<'tcx>,
+) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
+    debug!("normalize_provider(goal={:#?})", goal);
+
+    tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
+    tcx.infer_ctxt().enter_canonical_trait_query(
+        &goal,
+        |ocx, ParamEnvAnd { param_env, value: goal }| {
+            let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.substs).map(
+                |(predicate, span)| {
+                    traits::Obligation::new(
+                        tcx,
+                        ObligationCause::dummy_with_span(span),
+                        param_env,
+                        predicate,
+                    )
+                },
+            );
+            ocx.register_obligations(obligations);
+            let normalized_ty = tcx.type_of(goal.def_id).subst(tcx, goal.substs);
+            Ok(NormalizationResult { normalized_ty })
+        },
+    )
+}
+
 fn normalize_inherent_projection_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     goal: CanonicalProjectionGoal<'tcx>,
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index fa18f921ee4..f621673f1d6 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -36,9 +36,17 @@ pub enum DynKind {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum AliasKind {
+    /// A projection `<Type as Trait>::AssocType`.
+    /// Can get normalized away if monomorphic enough.
     Projection,
     Inherent,
+    /// An opaque type (usually from `impl Trait` in type aliases or function return types)
+    /// Can only be normalized away in RevealAll mode
     Opaque,
+    /// A type alias that actually checks its trait bounds.
+    /// Currently only used if the type alias references opaque types.
+    /// Can always be normalized away.
+    Weak,
 }
 
 /// Defines the kinds of types used by the type system.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0c7950bfd3d..9f698a3b6bf 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2052,6 +2052,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             }))
         }
 
+        ty::Alias(ty::Weak, data) => {
+            let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs);
+            clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
+        }
+
         ty::Param(ref p) => {
             if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
                 ImplTrait(bounds)
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index a1d2147cb49..dbaf6aaa853 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1424,6 +1424,7 @@ fn ty_auto_deref_stability<'tcx>(
                 continue;
             },
             ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
+            ty::Alias(ty::Weak, _) => unreachable!("should have been normalized away above"),
             ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"),
             ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
                 TyPosition::new_deref_stable_for_result(precedence, ty)
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
index d18f9387565..204019130ed 100644
--- a/src/tools/clippy/tests/ui/from_over_into.fixed
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -82,10 +82,4 @@ fn msrv_1_41() {
     }
 }
 
-type Opaque = impl Sized;
-struct IntoOpaque;
-impl Into<Opaque> for IntoOpaque {
-    fn into(self) -> Opaque {}
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index de8ff0b06bd..46e02847e30 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -82,10 +82,4 @@ fn msrv_1_41() {
     }
 }
 
-type Opaque = impl Sized;
-struct IntoOpaque;
-impl Into<Opaque> for IntoOpaque {
-    fn into(self) -> Opaque {}
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
index 3b280b7488a..bd62c655216 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
@@ -32,4 +32,10 @@ impl Into<u8> for ContainsVal {
     }
 }
 
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+    fn into(self) -> Opaque {}
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
index 251f1d84e74..bb966af4b0f 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -1,29 +1,12 @@
-error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into_unfixable.rs:11:1
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/from_over_into_unfixable.rs:35:15
    |
-LL | impl Into<InMacro> for String {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type Opaque = impl Sized;
+   |               ^^^^^^^^^^
    |
-   = help: replace the `Into` implementation with `From<std::string::String>`
-   = note: `-D clippy::from-over-into` implied by `-D warnings`
+   = 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: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into_unfixable.rs:19:1
-   |
-LL | impl Into<WeirdUpperSelf> for &'static [u8] {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: replace the `Into` implementation with `From<&'static [u8]>`
-
-error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into_unfixable.rs:28:1
-   |
-LL | impl Into<u8> for ContainsVal {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
-           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
-   = help: replace the `Into` implementation with `From<ContainsVal>`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs
index a2a30c8b931..4eff62b85ff 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.rs
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs
@@ -401,25 +401,3 @@ mod issue7344 {
         }
     }
 }
-
-mod issue10041 {
-    struct Bomb;
-
-    impl Bomb {
-        // Hidden <Rhs = Self> default generic parameter.
-        pub fn new() -> impl PartialOrd {
-            0i32
-        }
-    }
-
-    // TAIT with self-referencing bounds
-    type X = impl std::ops::Add<Output = X>;
-
-    struct Bomb2;
-
-    impl Bomb2 {
-        pub fn new() -> X {
-            0i32
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
index 2eaebfb5cac..2b053b462b1 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
@@ -92,21 +92,5 @@ LL | |             unimplemented!()
 LL | |         }
    | |_________^
 
-error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:410:9
-   |
-LL | /         pub fn new() -> impl PartialOrd {
-LL | |             0i32
-LL | |         }
-   | |_________^
-
-error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:421:9
-   |
-LL | /         pub fn new() -> X {
-LL | |             0i32
-LL | |         }
-   | |_________^
-
-error: aborting due to 14 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs
new file mode 100644
index 00000000000..7bc6fec10ba
--- /dev/null
+++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+#![warn(clippy::new_ret_no_self)]
+
+mod issue10041 {
+    struct Bomb;
+
+    impl Bomb {
+        // Hidden <Rhs = Self> default generic parameter.
+        pub fn new() -> impl PartialOrd {
+            0i32
+        }
+    }
+
+    // TAIT with self-referencing bounds
+    type X = impl std::ops::Add<Output = X>;
+
+    struct Bomb2;
+
+    impl Bomb2 {
+        pub fn new() -> X {
+            0i32
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr
new file mode 100644
index 00000000000..babb634fdcd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
+  --> $DIR/new_ret_no_self_overflow.rs:20:25
+   |
+LL |         pub fn new() -> X {
+   |                         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/impl-trait/nested-return-type2-tait.stderr b/tests/ui/impl-trait/nested-return-type2-tait.stderr
index a8eb69cfcb7..4383e8ab3a0 100644
--- a/tests/ui/impl-trait/nested-return-type2-tait.stderr
+++ b/tests/ui/impl-trait/nested-return-type2-tait.stderr
@@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait<Assoc = Sendable> {
    |                        ^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
-help: add this bound
-   |
-LL | type Sendable = impl Send + Duh;
-   |                           +++++
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/impl-trait/nested-return-type3-tait.stderr b/tests/ui/impl-trait/nested-return-type3-tait.stderr
index 5f58c8dca4a..d32944a0d72 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait.stderr
+++ b/tests/ui/impl-trait/nested-return-type3-tait.stderr
@@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait<Assoc = Sendable> {
    |                        ^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
-help: add this bound
-   |
-LL | type Sendable = impl Send + Duh;
-   |                           +++++
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.stderr b/tests/ui/impl-trait/nested-return-type3-tait2.stderr
index c07f6ead750..a2eddd11665 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait2.stderr
+++ b/tests/ui/impl-trait/nested-return-type3-tait2.stderr
@@ -8,10 +8,6 @@ LL | type Traitable = impl Trait<Assoc = Sendable>;
    |                             ^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
-help: add this bound
-   |
-LL | type Sendable = impl Send + Duh;
-   |                           +++++
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
index af9dfe25bb4..01c933473ea 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -1,5 +1,7 @@
 #![feature(type_alias_impl_trait)]
 
+// check-pass
+
 type Foo = impl PartialEq<(Foo, i32)>;
 
 struct Bar;
@@ -11,7 +13,6 @@ impl PartialEq<(Foo, i32)> for Bar {
 }
 
 fn foo() -> Foo {
-    //~^ ERROR can't compare `Bar` with `(Bar, i32)`
     Bar
 }
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
deleted file mode 100644
index 7b63a3d0b9f..00000000000
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0277]: can't compare `Bar` with `(Bar, i32)`
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13
-   |
-LL | fn foo() -> Foo {
-   |             ^^^ no implementation for `Bar == (Bar, i32)`
-LL |
-LL |     Bar
-   |     --- return type was inferred to be `Bar` here
-   |
-   = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
-   = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index fe62a8f3288..bbd60d4398b 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -20,6 +20,11 @@ LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |
    = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
               found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9
+   |
+LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unconstrained opaque type
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
index ad0a003e879..aab10be2de2 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl PartialEq<(Foo, i32)>;
@@ -13,6 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar {
 }
 
 fn foo() -> Foo {
+    //~^ ERROR can't compare `Bar` with `(Foo, i32)`
     Bar
 }
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
new file mode 100644
index 00000000000..b98b859a99b
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
@@ -0,0 +1,15 @@
+error[E0277]: can't compare `Bar` with `(Foo, i32)`
+  --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
+   |
+LL | fn foo() -> Foo {
+   |             ^^^ no implementation for `Bar == (Foo, i32)`
+LL |
+LL |     Bar
+   |     --- return type was inferred to be `Bar` here
+   |
+   = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar`
+   = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs
index 691047c8a40..f30377d6c16 100644
--- a/tests/ui/lint/lint-ctypes-73249-2.rs
+++ b/tests/ui/lint/lint-ctypes-73249-2.rs
@@ -1,7 +1,7 @@
 #![feature(type_alias_impl_trait)]
 #![deny(improper_ctypes)]
 
-pub trait Baz {}
+trait Baz {}
 
 impl Baz for () {}
 
@@ -9,7 +9,7 @@ type Qux = impl Baz;
 
 fn assign() -> Qux {}
 
-pub trait Foo {
+trait Foo {
     type Assoc: 'static;
 }
 
@@ -18,12 +18,12 @@ impl Foo for () {
 }
 
 #[repr(transparent)]
-pub struct A<T: Foo> {
+struct A<T: Foo> {
     x: &'static <T as Foo>::Assoc,
 }
 
 extern "C" {
-    pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux`
+    fn lint_me() -> A<()>; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr
index 8073c33dd46..49fa54114b2 100644
--- a/tests/ui/lint/lint-ctypes-73249-2.stderr
+++ b/tests/ui/lint/lint-ctypes-73249-2.stderr
@@ -1,8 +1,8 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73249-2.rs:26:25
+  --> $DIR/lint-ctypes-73249-2.rs:26:21
    |
-LL |     pub fn lint_me() -> A<()>;
-   |                         ^^^^^ not FFI-safe
+LL |     fn lint_me() -> A<()>;
+   |                     ^^^^^ not FFI-safe
    |
    = note: opaque types have no C equivalent
 note: the lint level is defined here
diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs
index 145ba784f7c..fc11f23a104 100644
--- a/tests/ui/lint/lint-ctypes-73251-1.rs
+++ b/tests/ui/lint/lint-ctypes-73251-1.rs
@@ -1,13 +1,13 @@
 #![feature(type_alias_impl_trait)]
 #![deny(improper_ctypes)]
 
-pub trait Baz {}
+trait Baz {}
 
 impl Baz for u32 {}
 
 type Qux = impl Baz;
 
-pub trait Foo {
+trait Foo {
     type Assoc;
 }
 
@@ -20,7 +20,7 @@ fn assign() -> Qux {
 }
 
 extern "C" {
-    pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `Qux`
+    fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `Qux`
 }
 
 fn main() {}
diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr
index 9f43576ad73..b4eb921b97e 100644
--- a/tests/ui/lint/lint-ctypes-73251-1.stderr
+++ b/tests/ui/lint/lint-ctypes-73251-1.stderr
@@ -1,8 +1,8 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73251-1.rs:23:25
+  --> $DIR/lint-ctypes-73251-1.rs:23:21
    |
-LL |     pub fn lint_me() -> <u32 as Foo>::Assoc;
-   |                         ^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn lint_me() -> <u32 as Foo>::Assoc;
+   |                     ^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: opaque types have no C equivalent
 note: the lint level is defined here
diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs
index df71a945796..fbe0a58f3b5 100644
--- a/tests/ui/lint/lint-ctypes-73251-2.rs
+++ b/tests/ui/lint/lint-ctypes-73251-2.rs
@@ -33,7 +33,7 @@ fn use_of_b() -> AliasB {
 }
 
 extern "C" {
-    pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `AliasA`
+    fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `AliasA`
 }
 
 fn main() {}
diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr
index 0b3de379c19..e44cd45bd30 100644
--- a/tests/ui/lint/lint-ctypes-73251-2.stderr
+++ b/tests/ui/lint/lint-ctypes-73251-2.stderr
@@ -1,8 +1,8 @@
 error: `extern` block uses type `AliasA`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73251-2.rs:36:25
+  --> $DIR/lint-ctypes-73251-2.rs:36:21
    |
-LL |     pub fn lint_me() -> <AliasB as TraitB>::Assoc;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+LL |     fn lint_me() -> <AliasB as TraitB>::Assoc;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: opaque types have no C equivalent
 note: the lint level is defined here
diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs
index ebc2ca77b67..a00d1a75aec 100644
--- a/tests/ui/lint/lint-ctypes-73251.rs
+++ b/tests/ui/lint/lint-ctypes-73251.rs
@@ -3,7 +3,7 @@
 #![feature(type_alias_impl_trait)]
 #![deny(improper_ctypes)]
 
-pub trait Foo {
+trait Foo {
     type Assoc;
 }
 
@@ -16,7 +16,7 @@ type Bar = impl Foo<Assoc = u32>;
 fn assign() -> Bar {}
 
 extern "C" {
-    pub fn lint_me() -> <Bar as Foo>::Assoc;
+    fn lint_me() -> <Bar as Foo>::Assoc;
 }
 
 fn main() {}
diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs
index b7cc38e99fc..5faeac9ed4c 100644
--- a/tests/ui/lint/opaque-ty-ffi-unsafe.rs
+++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -3,12 +3,12 @@
 
 type A = impl Fn();
 
-pub fn ret_closure() -> A {
+pub(crate) fn ret_closure() -> A {
     || {}
 }
 
 extern "C" {
-    pub fn a(_: A);
+    pub(crate) fn a(_: A);
     //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes]
 }
 
diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
index 33aa95854e3..ba9e18bcce5 100644
--- a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -1,8 +1,8 @@
 error: `extern` block uses type `A`, which is not FFI-safe
-  --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
+  --> $DIR/opaque-ty-ffi-unsafe.rs:11:24
    |
-LL |     pub fn a(_: A);
-   |                 ^ not FFI-safe
+LL |     pub(crate) fn a(_: A);
+   |                        ^ not FFI-safe
    |
    = note: opaque types have no C equivalent
 note: the lint level is defined here
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
index a1584581e6c..d9f7c7809b9 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
@@ -4,9 +4,9 @@
 #![allow(dead_code)]
 
 mod m {
-    type Foo = impl std::fmt::Debug;
+    pub(crate) type Foo = impl std::fmt::Debug;
 
-    pub fn foo() -> Foo {
+    pub(crate) fn foo() -> Foo {
         22_u32
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs
new file mode 100644
index 00000000000..5a9e87c0919
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+use std::fmt::{Debug, Display};
+
+struct Struct<V: Display>(Option<V>);
+
+// Make sure that, in contrast to type aliases without opaque types,
+// we actually do a wf check for the aliased type.
+type Foo<T: Debug> = (impl Debug, Struct<T>);
+//~^ ERROR: `T` doesn't implement `std::fmt::Display`
+
+fn foo<U: Debug + Display>() -> Foo<U> {
+    (Vec::<U>::new(), Struct(None))
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr
new file mode 100644
index 00000000000..a845cba7716
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr
@@ -0,0 +1,20 @@
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/bounds-are-checked3.rs:9:35
+   |
+LL | type Foo<T: Debug> = (impl Debug, Struct<T>);
+   |                                   ^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `Struct`
+  --> $DIR/bounds-are-checked3.rs:5:18
+   |
+LL | struct Struct<V: Display>(Option<V>);
+   |                  ^^^^^^^ required by this bound in `Struct`
+help: consider further restricting this bound
+   |
+LL | type Foo<T: Debug + std::fmt::Display> = (impl Debug, Struct<T>);
+   |                   +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/bounds.rs b/tests/ui/type-alias-impl-trait/bounds.rs
new file mode 100644
index 00000000000..dc05b70c5cc
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/bounds.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+use std::fmt::Debug;
+
+// No need to report the `type_alias_bounds` lint, as
+// the moment an opaque type is mentioned, we actually do check
+// type alias bounds.
+type Foo<T: Debug> = (impl Debug, usize);
+
+fn foo<U: Debug>() -> Foo<U> {
+    (Vec::<U>::new(), 1234)
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr
index 00b0dbbb583..c923eb08ab3 100644
--- a/tests/ui/type-alias-impl-trait/coherence.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.stderr
@@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
 LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
    | |                                       |
-   | |                                       type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
+   | |                                       `AliasOfForeignType<T>` is not defined in the current crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
index 8b51f55715e..4d84b2cbbe9 100644
--- a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
+++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
@@ -11,12 +11,12 @@ type Foo = impl std::fmt::Display;
 type Bar = impl std::fmt::Display;
 
 mod foo {
-    pub fn foo() -> super::Foo {
+    pub(crate) fn foo() -> super::Foo {
         "foo"
     }
 
-    pub mod bar {
-        pub fn bar() -> crate::Bar {
+    pub(crate) mod bar {
+        pub(crate) fn bar() -> crate::Bar {
             1
         }
     }
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
index c73288329b0..bc9280127ac 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
@@ -4,11 +4,11 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
 LL | fn underconstrain<T>(_: T) -> Underconstrained<T> {
    |                               ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
    |
-note: required by a bound in `Underconstrained`
+note: required by a bound on the type alias `Underconstrained`
   --> $DIR/generic_underconstrained.rs:6:26
    |
 LL | type Underconstrained<T: Trait> = impl Send;
-   |                          ^^^^^ required by this bound in `Underconstrained`
+   |                          ^^^^^ required by this bound
 help: consider restricting type parameter `T`
    |
 LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> {
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index d77d978aa44..fdc9ec090db 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -4,11 +4,11 @@ error[E0277]: `U` doesn't implement `Debug`
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                                 ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-note: required by a bound in `Underconstrained`
+note: required by a bound on the type alias `Underconstrained`
   --> $DIR/generic_underconstrained2.rs:5:26
    |
 LL | type Underconstrained<T: std::fmt::Debug> = impl Send;
-   |                          ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained`
+   |                          ^^^^^^^^^^^^^^^ required by this bound
 help: consider restricting type parameter `U`
    |
 LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
@@ -20,11 +20,11 @@ error[E0277]: `V` doesn't implement `Debug`
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                                           ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-note: required by a bound in `Underconstrained2`
+note: required by a bound on the type alias `Underconstrained2`
   --> $DIR/generic_underconstrained2.rs:13:27
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl Send;
-   |                           ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained2`
+   |                           ^^^^^^^^^^^^^^^ required by this bound
 help: consider restricting type parameter `V`
    |
 LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> {
diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs
new file mode 100644
index 00000000000..00d1a1a226d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs
@@ -0,0 +1,14 @@
+#![feature(type_alias_impl_trait)]
+#![feature(auto_traits)]
+
+type Alias = (impl Sized, u8);
+
+auto trait Trait {}
+impl Trait for Alias {}
+//~^ ERROR traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias`
+
+fn _def() -> Alias {
+    (42, 42)
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr
new file mode 100644
index 00000000000..c312ee7dece
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr
@@ -0,0 +1,11 @@
+error[E0321]: traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias`
+  --> $DIR/impl_for_weak_alias.rs:7:1
+   |
+LL | impl Trait for Alias {}
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Trait` if and only if `Trait` is one of the trait object's trait bounds
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0321`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
index 4a11bb5020e..b89c3e4590f 100644
--- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs
@@ -1,9 +1,10 @@
 #![feature(type_alias_impl_trait)]
 
+// check-pass
+
 type Foo = impl Fn() -> Foo;
 
 fn foo() -> Foo {
-//~^ ERROR: overflow evaluating the requirement
     foo
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
deleted file mode 100644
index 0a34e8486a5..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0275]: overflow evaluating the requirement `Foo: Sized`
-  --> $DIR/issue-53398-cyclic-types.rs:5:13
-   |
-LL | fn foo() -> Foo {
-   |             ^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`)
-   = note: required because it appears within the type `fn() -> Foo {foo}`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/obligation_ice.rs b/tests/ui/type-alias-impl-trait/obligation_ice.rs
new file mode 100644
index 00000000000..5aef04ff19c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/obligation_ice.rs
@@ -0,0 +1,17 @@
+#![feature(type_alias_impl_trait)]
+// check-pass
+
+use std::iter::{once, Chain};
+
+trait Trait<'a, 'b: 'a> {}
+
+impl<'a, 'b: 'a, T> Trait<'a, 'b> for std::iter::Cloned<T> {}
+
+type I<'a, 'b: 'a, A: Trait<'a, 'b>> = Chain<A, impl Iterator<Item = &'static str>>;
+fn test2<'a, 'b, A: Trait<'a, 'b> + Iterator<Item = &'static str>>(x: A) -> I<'a, 'b, A> {
+    x.chain(once("5"))
+}
+
+fn main() {
+    assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::<Vec<_>>());
+}
diff --git a/tests/ui/type-alias-impl-trait/privacy.rs b/tests/ui/type-alias-impl-trait/privacy.rs
new file mode 100644
index 00000000000..aa092f6f8ec
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/privacy.rs
@@ -0,0 +1,8 @@
+#![feature(type_alias_impl_trait)]
+
+type Foo = (impl Sized, u8);
+pub fn foo() -> Foo {
+    //~^ ERROR private type alias `Foo` in public interface
+    (42, 42)
+}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/privacy.stderr b/tests/ui/type-alias-impl-trait/privacy.stderr
new file mode 100644
index 00000000000..e8c6039cdc8
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/privacy.stderr
@@ -0,0 +1,11 @@
+error[E0446]: private type alias `Foo` in public interface
+  --> $DIR/privacy.rs:4:1
+   |
+LL | type Foo = (impl Sized, u8);
+   | -------- `Foo` declared as private
+LL | pub fn foo() -> Foo {
+   | ^^^^^^^^^^^^^^^^^^^ can't leak private type alias
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs
index d40715717d4..18f09b54867 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-3.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs
@@ -1,9 +1,9 @@
-// run-pass
 #![feature(type_alias_impl_trait)]
 
 type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
 
 fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+    //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
     i
 }
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
new file mode 100644
index 00000000000..4155a114b4f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
@@ -0,0 +1,15 @@
+error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
+  --> $DIR/self-referential-3.rs:5:31
+   |
+LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
+   |                               ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
+LL |
+LL |     i
+   |     - return type was inferred to be `&i32` here
+   |
+   = help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
+   = help: the trait `PartialEq` is implemented for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs
index 3ff5406a382..34b7c24df9f 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential.rs
@@ -10,7 +10,7 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
 type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
 
 fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
-    //~^ ERROR can't compare `&i32` with `(i32, &i32)`
+    //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})`
     (42, i)
 }
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr
index aff489d70e3..9a17d495b62 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential.stderr
@@ -10,16 +10,16 @@ LL |     i
    = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
    = help: the trait `PartialEq` is implemented for `i32`
 
-error[E0277]: can't compare `&i32` with `(i32, &i32)`
+error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})`
   --> $DIR/self-referential.rs:12:31
    |
 LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
-   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, &i32)`
+   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})`
 LL |
 LL |     (42, i)
    |     ------- return type was inferred to be `(i32, &i32)` here
    |
-   = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32`
+   = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32`
    = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
index 07c891f0638..4e7388517a5 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
@@ -4,20 +4,20 @@
 
 // Regression test for issue #61863
 
-pub trait MyTrait {}
+trait MyTrait {}
 
 #[derive(Debug)]
-pub struct MyStruct {
+struct MyStruct {
     v: u64,
 }
 
 impl MyTrait for MyStruct {}
 
-pub fn bla() -> TE {
+fn bla() -> TE {
     return MyStruct { v: 1 };
 }
 
-pub fn bla2() -> TE {
+fn bla2() -> TE {
     bla()
 }
 
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
index e9032433494..24f5cc8c733 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -25,6 +25,11 @@ LL |         fn dont_define_this(_private: Private) {}
    |                                       ^^^^^^^
    = note: expected signature `fn(Private)`
               found signature `fn(MyPrivate)`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/unnameable_type.rs:20:5
+   |
+LL |     fn dont_define_this(_private: MyPrivate) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors