From d80d7ea1e325ded1b8b57204cbf98e65b6e0957c Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 8 Feb 2024 12:28:35 +0000
Subject: [PATCH] Add some tests for associated type normalization edge cases

---
 tests/ui/privacy/projections.rs      | 60 +++++++++++++++++++++++++++
 tests/ui/privacy/projections.stderr  | 62 ++++++++++++++++++++++++++++
 tests/ui/privacy/projections2.rs     | 38 +++++++++++++++++
 tests/ui/privacy/projections2.stderr | 34 +++++++++++++++
 4 files changed, 194 insertions(+)
 create mode 100644 tests/ui/privacy/projections.rs
 create mode 100644 tests/ui/privacy/projections.stderr
 create mode 100644 tests/ui/privacy/projections2.rs
 create mode 100644 tests/ui/privacy/projections2.stderr

diff --git a/tests/ui/privacy/projections.rs b/tests/ui/privacy/projections.rs
new file mode 100644
index 00000000000..0e6590de4f5
--- /dev/null
+++ b/tests/ui/privacy/projections.rs
@@ -0,0 +1,60 @@
+mod m {
+    struct Priv;
+    pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak`
+}
+
+trait Trait {
+    type A<T>;
+}
+
+impl Trait for u8 {
+    type A<T> = u8;
+}
+
+fn check() -> <u8 as Trait>::A<m::Leak> {
+    //~^ ERROR: `Priv` is private
+    0
+}
+
+trait Trait2 {
+    type A<T>;
+}
+
+impl Trait2 for u8 {
+    type A<T> = m::Leak;
+    //~^ ERROR: `Priv` is private
+    //~| ERROR: private type `Priv` in public interface
+}
+
+fn check2() -> <u8 as Trait2>::A<u32> {
+    //~^ ERROR: `Priv` is private
+    todo!()
+}
+
+trait Trait3 {
+    type A<T: Trait>;
+}
+
+impl Trait3 for u8 {
+    type A<T: Trait> = T::A<m::Leak>;
+    //~^ ERROR: `Priv` is private
+    //~| ERROR: private type `Priv` in public interface
+}
+
+fn check3() -> <u8 as Trait3>::A<u8> {
+    todo!()
+}
+
+trait Trait4 {
+    type A<T: Trait3>;
+}
+
+impl Trait4 for u8 {
+    type A<T: Trait3> = T::A<u8>;
+}
+
+fn check4() -> <u8 as Trait4>::A<u8> {
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr
new file mode 100644
index 00000000000..010d77998e3
--- /dev/null
+++ b/tests/ui/privacy/projections.stderr
@@ -0,0 +1,62 @@
+warning: type `Priv` is more private than the item `Leak`
+  --> $DIR/projections.rs:3:5
+   |
+LL |     pub type Leak = Priv;
+   |     ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)`
+   |
+note: but type `Priv` is only usable at visibility `pub(self)`
+  --> $DIR/projections.rs:2:5
+   |
+LL |     struct Priv;
+   |     ^^^^^^^^^^^
+   = note: `#[warn(private_interfaces)]` on by default
+
+error[E0446]: private type `Priv` in public interface
+  --> $DIR/projections.rs:24:5
+   |
+LL |     struct Priv;
+   |     ----------- `Priv` declared as private
+...
+LL |     type A<T> = m::Leak;
+   |     ^^^^^^^^^ can't leak private type
+
+error[E0446]: private type `Priv` in public interface
+  --> $DIR/projections.rs:39:5
+   |
+LL |     struct Priv;
+   |     ----------- `Priv` declared as private
+...
+LL |     type A<T: Trait> = T::A<m::Leak>;
+   |     ^^^^^^^^^^^^^^^^ can't leak private type
+
+error: type `Priv` is private
+  --> $DIR/projections.rs:14:15
+   |
+LL | fn check() -> <u8 as Trait>::A<m::Leak> {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^ private type
+
+error: type `Priv` is private
+  --> $DIR/projections.rs:29:39
+   |
+LL |   fn check2() -> <u8 as Trait2>::A<u32> {
+   |  _______________________________________^
+LL | |
+LL | |     todo!()
+LL | | }
+   | |_^ private type
+
+error: type `Priv` is private
+  --> $DIR/projections.rs:24:17
+   |
+LL |     type A<T> = m::Leak;
+   |                 ^^^^^^^ private type
+
+error: type `Priv` is private
+  --> $DIR/projections.rs:39:24
+   |
+LL |     type A<T: Trait> = T::A<m::Leak>;
+   |                        ^^^^^^^^^^^^^ private type
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/tests/ui/privacy/projections2.rs b/tests/ui/privacy/projections2.rs
new file mode 100644
index 00000000000..1afbf6d196e
--- /dev/null
+++ b/tests/ui/privacy/projections2.rs
@@ -0,0 +1,38 @@
+mod m {
+    use super::*;
+    struct Priv;
+    pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak`
+
+    trait Trait3 {
+        type A<T: Trait>;
+    }
+
+    impl Trait3 for u8 {
+        type A<T: Trait> = T::A<Leak>;
+    }
+
+    pub trait Trait4 {
+        type A<T: Trait>;
+    }
+
+    impl Trait4 for u8 {
+        type A<T: Trait> = <u8 as Trait3>::A<T>;
+        //~^ ERROR: private associated type `Trait3::A` in public interface
+        //~| ERROR: private trait `Trait3` in public interface
+    }
+}
+
+pub trait Trait {
+    type A<T>;
+}
+
+impl Trait for u8 {
+    type A<T> = u8;
+}
+use m::*;
+
+fn check4() -> <u8 as Trait4>::A<u8> {
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/privacy/projections2.stderr b/tests/ui/privacy/projections2.stderr
new file mode 100644
index 00000000000..6eae9643c5a
--- /dev/null
+++ b/tests/ui/privacy/projections2.stderr
@@ -0,0 +1,34 @@
+warning: type `Priv` is more private than the item `Leak`
+  --> $DIR/projections2.rs:4:5
+   |
+LL |     pub type Leak = Priv;
+   |     ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)`
+   |
+note: but type `Priv` is only usable at visibility `pub(self)`
+  --> $DIR/projections2.rs:3:5
+   |
+LL |     struct Priv;
+   |     ^^^^^^^^^^^
+   = note: `#[warn(private_interfaces)]` on by default
+
+error[E0446]: private associated type `Trait3::A` in public interface
+  --> $DIR/projections2.rs:19:9
+   |
+LL |         type A<T: Trait>;
+   |         ---------------- `Trait3::A` declared as private
+...
+LL |         type A<T: Trait> = <u8 as Trait3>::A<T>;
+   |         ^^^^^^^^^^^^^^^^ can't leak private associated type
+
+error[E0446]: private trait `Trait3` in public interface
+  --> $DIR/projections2.rs:19:9
+   |
+LL |     trait Trait3 {
+   |     ------------ `Trait3` declared as private
+...
+LL |         type A<T: Trait> = <u8 as Trait3>::A<T>;
+   |         ^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0446`.