From 63a54d93be33bb1c0357c48532df778f6f2a416b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Fri, 14 Jun 2024 15:30:11 +0200
Subject: [PATCH] Don't suppress lint type_alias_bounds for ty aliases
 containing inherent assoc tys

---
 compiler/rustc_lint/src/builtin.rs            | 30 ++++++++-----------
 compiler/rustc_type_ir/src/visit.rs           |  4 ---
 .../type-alias-bounds-are-enforced.rs         | 20 -------------
 .../type-alias-bounds.rs                      | 29 ++++++++++++++++++
 .../type-alias-bounds.stderr                  | 15 ++++++++++
 5 files changed, 56 insertions(+), 42 deletions(-)
 delete mode 100644 tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
 create mode 100644 tests/ui/associated-inherent-types/type-alias-bounds.rs
 create mode 100644 tests/ui/associated-inherent-types/type-alias-bounds.stderr

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9ebada0fff3..40b336cd5ea 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1425,30 +1425,27 @@ impl TypeAliasBounds {
 
 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
+        let hir::ItemKind::TyAlias(hir_ty, generics) = &item.kind else { return };
+
+        // There must not be a where clause.
+        if generics.predicates.is_empty() {
+            return;
+        }
 
         // Bounds of lazy type aliases and TAITs are respected.
         if cx.tcx.type_alias_is_lazy(item.owner_id) {
             return;
         }
 
-        let ty = cx.tcx.type_of(item.owner_id).skip_binder();
-        if ty.has_inherent_projections() {
-            // Bounds of type aliases that contain opaque types or inherent projections are
-            // respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X =
-            // Type::Inherent;`.
-            return;
-        }
-
-        // There must not be a where clause
-        if type_alias_generics.predicates.is_empty() {
-            return;
-        }
+        // NOTE(inherent_associated_types): While we currently do take some bounds in type
+        // aliases into consideration during IAT *selection*, we don't perform full use+def
+        // site wfchecking for such type aliases. Therefore TAB should still trigger.
+        // See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`.
 
         let mut where_spans = Vec::new();
         let mut inline_spans = Vec::new();
         let mut inline_sugg = Vec::new();
-        for p in type_alias_generics.predicates {
+        for p in generics.predicates {
             let span = p.span();
             if p.in_where_clause() {
                 where_spans.push(span);
@@ -1469,10 +1466,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
             cx.emit_span_lint(
                 TYPE_ALIAS_BOUNDS,
                 where_spans,
-                BuiltinTypeAliasWhereClause {
-                    suggestion: type_alias_generics.where_clause_span,
-                    sub,
-                },
+                BuiltinTypeAliasWhereClause { suggestion: generics.where_clause_span, sub },
             );
         }
 
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 6ec38b78fc2..d5e114b2175 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
         self.has_type_flags(TypeFlags::HAS_ALIAS)
     }
 
-    fn has_inherent_projections(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_INHERENT)
-    }
-
     fn has_opaque_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
     }
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
deleted file mode 100644
index 5ac7e1e58b8..00000000000
--- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ compile-flags: --crate-type=lib
-//@ check-pass
-
-#![feature(inherent_associated_types)]
-#![allow(incomplete_features)]
-
-// Bounds on the self type play a major role in the resolution of inherent associated types (*).
-// As a result of that, if a type alias contains any then its bounds have to be respected and the
-// lint `type_alias_bounds` should not fire.
-
-#![deny(type_alias_bounds)]
-
-pub type Alias<T: Bound> = (Source<T>::Assoc,);
-
-pub struct Source<T>(T);
-pub trait Bound {}
-
-impl<T: Bound> Source<T> {
-    pub type Assoc = ();
-}
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds.rs b/tests/ui/associated-inherent-types/type-alias-bounds.rs
new file mode 100644
index 00000000000..c27bcbed43a
--- /dev/null
+++ b/tests/ui/associated-inherent-types/type-alias-bounds.rs
@@ -0,0 +1,29 @@
+//@ compile-flags: --crate-type=lib
+//@ check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// FIXME(inherent_associated_types):
+// While we currently do take some clauses of the ParamEnv into consideration
+// when performing IAT selection, we do not perform full well-formedness checking
+// for (eager) type alias definition and usage sites.
+//
+// Therefore it's *correct* for lint `type_alias_bounds` to fire here despite the
+// fact that removing `Bound` from `T` in `Alias` would lead to an error!
+//
+// Obviously, the present situation isn't ideal and we should fix it in one way
+// or another. Either we somehow delay IAT selection until after HIR ty lowering
+// to avoid the need to specify any bounds inside (eager) type aliases or we
+// force the overarching type alias to be *lazy* (similar to TAITs) which would
+// automatically lead to full wfchecking and lint TAB getting suppressed.
+
+pub type Alias<T: Bound> = (Source<T>::Assoc,);
+//~^ WARN bounds on generic parameters are not enforced in type aliases
+
+pub struct Source<T>(T);
+pub trait Bound {}
+
+impl<T: Bound> Source<T> {
+    pub type Assoc = ();
+}
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds.stderr b/tests/ui/associated-inherent-types/type-alias-bounds.stderr
new file mode 100644
index 00000000000..c5d0e9e5041
--- /dev/null
+++ b/tests/ui/associated-inherent-types/type-alias-bounds.stderr
@@ -0,0 +1,15 @@
+warning: bounds on generic parameters are not enforced in type aliases
+  --> $DIR/type-alias-bounds.rs:21:19
+   |
+LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
+   |                   ^^^^^
+   |
+   = note: `#[warn(type_alias_bounds)]` on by default
+help: the bound will not be checked when the type alias is used, and should be removed
+   |
+LL - pub type Alias<T: Bound> = (Source<T>::Assoc,);
+LL + pub type Alias<T> = (Source<T>::Assoc,);
+   |
+
+warning: 1 warning emitted
+