about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-08-14 15:02:06 +0000
committerMichael Goulet <michael@errs.io>2025-08-14 15:06:18 +0000
commitb0ec0ec10d7aca46f6b22e9bba873d09c0388f07 (patch)
tree0f6d631fbf0ccc78fd120d5cb2c62baa8c79cccc
parent2f85c80f9cb3c2e34904dd1d5ff80ed6f4cd6264 (diff)
downloadrust-b0ec0ec10d7aca46f6b22e9bba873d09c0388f07.tar.gz
rust-b0ec0ec10d7aca46f6b22e9bba873d09c0388f07.zip
Add test
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr30
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr30
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.rs46
3 files changed, 106 insertions, 0 deletions
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
new file mode 100644
index 00000000000..4652bf5e3c5
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+   |
+LL |     x.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in the trait `Trait1`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.method();
+LL +     Trait1::method(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.method();
+LL +     Trait2::method(&x);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
new file mode 100644
index 00000000000..afacb3a7d52
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+   |
+LL |     x.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in the trait `Trait1`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `Trait2`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.method();
+LL +     Trait1::method(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.method();
+LL +     Trait2::method(&x);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
new file mode 100644
index 00000000000..3dd63df3f39
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
@@ -0,0 +1,46 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// See the code below.
+//
+// We were using `DeepRejectCtxt` to ensure that `assemble_inherent_candidates_from_param`
+// did not rely on the param-env being eagerly normalized. Since aliases unify with all
+// types, this meant that a rigid param-env candidate like `<T as Deref>::Target: Trait1`
+// would be registered as a "WhereClauseCandidate", which is treated as inherent. Since
+// we evaluate these candidates for all self types in the deref chain, this candidate
+// would be satisfied for `<T as Deref>::Target`, meaning that it would be preferred over
+// an "extension" candidate like `<T as Deref>::Target: Trait2` even though it holds.
+// This is problematic, since it causes ambiguities to be broken somewhat arbitrarily.
+// And as a side-effect, it also caused our computation of "used" traits to be miscalculated
+// since inherent candidates don't count as an import usage.
+
+use std::ops::Deref;
+
+trait Trait1 {
+    fn method(&self) {
+        println!("1");
+    }
+}
+
+trait Trait2 {
+    fn method(&self) {
+        println!("2");
+    }
+}
+impl<T: Other + ?Sized> Trait2 for T {}
+
+trait Other {}
+
+fn foo<T>(x: T)
+where
+    T: Deref,
+    <T as Deref>::Target: Trait1 + Other,
+{
+    // Make sure that we don't prefer methods from where clauses for rigid aliases,
+    // just for params. We could revisit this behavior, but it would be a lang change.
+    x.method();
+    //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}