about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-17 00:33:29 +0000
committerbors <bors@rust-lang.org>2023-06-17 00:33:29 +0000
commit0cc541e4b2eb957e71490cf44df1ac09f6d18132 (patch)
tree7a80e16efcfeeaa7f1892a4b1bb405cd7d7f2c51
parent670a0edaa9d80683df8db81554890710e79f8024 (diff)
parent79c2c986a29faf7be042a5ab40975b9b8f1c2575 (diff)
downloadrust-0cc541e4b2eb957e71490cf44df1ac09f6d18132.tar.gz
rust-0cc541e4b2eb957e71490cf44df1ac09f6d18132.zip
Auto merge of #108860 - oli-obk:tait_alias, r=compiler-errors
Add `AliasKind::Weak` for type aliases.

`type Foo<T: Debug> = Bar<T>;` does not check `T: Debug` at use sites of `Foo<NotDebug>`, because in contrast to a

```rust
trait Identity {
    type Identity;
}
impl<T: Debug> Identity for T {
    type Identity = T;
}
<NotDebug as Identity>::Identity
```

type aliases do not exist in the type system, but are expanded to their aliased type immediately when going from HIR to the type layer.

Similarly:

* a private type alias for a public type is a completely fine thing, even though it makes it a bit hard to write out complex times sometimes
* rustdoc expands the type alias, even though often times users use them for documentation purposes
* diagnostics show the expanded type, which is confusing if the user wrote a type alias and the diagnostic talks about another type that they don't know about.

For type alias impl trait, these issues do not actually apply in most cases, but sometimes you have a type alias impl trait like `type Foo<T: Debug> = (impl Debug, Bar<T>);`, which only really checks it for `impl Debug`, but by accident prevents `Bar<T>` from only being instantiated after proving `T: Debug`. This PR makes sure that we always check these bounds explicitly and don't rely on an implementation accident.

To not break all the type aliases out there, we only use it when the type alias contains an opaque type. We can decide to do this for all type aliases over an edition.

Or we can later extend this to more types if we figure out the back-compat concerns with suddenly checking such bounds.

As a side effect, easily allows fixing https://github.com/rust-lang/rust/issues/108617, which I did.

fixes https://github.com/rust-lang/rust/issues/108617
-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