about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <rust@boxyuwu.dev>2025-05-27 18:21:24 +0100
committerBoxy <rust@boxyuwu.dev>2025-06-17 14:18:34 +0100
commit2a950b5637febcf7e526942d6755698defcec2a6 (patch)
treecfaefafa40d2af74e044d0ddc94cd16834855cdd
parent442862bc78b24f6019e4f3e32cfe2380dd480f26 (diff)
downloadrust-2a950b5637febcf7e526942d6755698defcec2a6.tar.gz
rust-2a950b5637febcf7e526942d6755698defcec2a6.zip
Test whether we use DeepRejectCtxt
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs12
-rw-r--r--tests/ui/associated-inherent-types/impl_params_are_infers.rs34
-rw-r--r--tests/ui/associated-inherent-types/impl_params_are_infers.stderr20
3 files changed, 62 insertions, 4 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index fd8c702a76b..ea4194079a6 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -414,10 +414,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                             // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
                             // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
                             //
-                            // We don't really care about a depth limit here because we're only working with user-written types
-                            // and if they wrote a type that would take hours to walk then that's kind of on them. On the other
-                            // hand the default depth limit is relatively low and could realistically be hit by users in normal
-                            // cases.
+                            // We don't really care about a depth limit here because we're only working with user-written
+                            // types and if they wrote a type that would take hours to walk then that's kind of on them. On
+                            // the other hand the default depth limit is relatively low and could realistically be hit by
+                            // users in normal cases.
+                            //
+                            // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
+                            // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
+                            // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
                             ty::DeepRejectCtxt::relate_rigid_infer(self.tcx)
                                 .types_may_unify_with_depth(self_ty, impl_ty, usize::MAX)
                         })
diff --git a/tests/ui/associated-inherent-types/impl_params_are_infers.rs b/tests/ui/associated-inherent-types/impl_params_are_infers.rs
new file mode 100644
index 00000000000..55d29a35a23
--- /dev/null
+++ b/tests/ui/associated-inherent-types/impl_params_are_infers.rs
@@ -0,0 +1,34 @@
+#![feature(inherent_associated_types)]
+#![expect(incomplete_features)]
+
+// Test whether IAT resolution in item signatures will actually instantiate the
+// impl's params with infers before equating self types, or if we "cheat" and
+// use a heuristic (e.g. DeepRejectCtxt).
+
+struct Foo<T, U, V>(T, U, V);
+
+impl<T> Foo<T, T, u8> {
+    type IAT = u8;
+}
+
+impl<T, U> Foo<T, U, u16> {
+    type IAT = u16;
+}
+
+trait Identity {
+    type This;
+}
+impl<T> Identity for T {
+    type This = T;
+}
+
+struct Bar<T, U> {
+    // It would be illegal to resolve to `Foo<T, T, u8>::IAT`  as  `T` and `U` are
+    // different types. However, currently we treat all impl-side params sort of like
+    // they're infers and assume they can unify with anything, so we consider it a
+    // valid candidate.
+    field: Foo<T, U, <u16 as Identity>::This>::IAT,
+    //~^ ERROR: multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/impl_params_are_infers.stderr b/tests/ui/associated-inherent-types/impl_params_are_infers.stderr
new file mode 100644
index 00000000000..fd31693cbed
--- /dev/null
+++ b/tests/ui/associated-inherent-types/impl_params_are_infers.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/impl_params_are_infers.rs:30:48
+   |
+LL |     field: Foo<T, U, <u16 as Identity>::This>::IAT,
+   |                                                ^^^ multiple `IAT` found
+   |
+note: candidate #1 is defined in an impl for the type `Foo<T, T, u8>`
+  --> $DIR/impl_params_are_infers.rs:11:5
+   |
+LL |     type IAT = u8;
+   |     ^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Foo<T, U, u16>`
+  --> $DIR/impl_params_are_infers.rs:15:5
+   |
+LL |     type IAT = u16;
+   |     ^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.