about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--tests/ui/traits/object/no-incomplete-inference.current.stderr16
-rw-r--r--tests/ui/traits/object/no-incomplete-inference.next.stderr16
-rw-r--r--tests/ui/traits/object/no-incomplete-inference.rs18
4 files changed, 62 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3a2f9e8ca17..1b9b68fa980 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1919,12 +1919,23 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // impl `impl<T: ?Sized> Any for T { .. }`. This really shouldn't exist but is
         // necessary due to #57893. We again arbitrarily prefer the applicable candidate
         // with the lowest index.
+        //
+        // We do not want to use these impls to guide inference in case a user-written impl
+        // may also apply.
         let object_bound = candidates
             .iter()
             .filter_map(|c| if let ObjectCandidate(i) = c.candidate { Some(i) } else { None })
             .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
         match object_bound {
-            Some(Some(index)) => return Some(ObjectCandidate(index)),
+            Some(Some(index)) => {
+                return if has_non_region_infer
+                    && candidates.iter().any(|c| matches!(c.candidate, ImplCandidate(_)))
+                {
+                    None
+                } else {
+                    Some(ObjectCandidate(index))
+                };
+            }
             Some(None) => {}
             None => return None,
         }
diff --git a/tests/ui/traits/object/no-incomplete-inference.current.stderr b/tests/ui/traits/object/no-incomplete-inference.current.stderr
new file mode 100644
index 00000000000..3c6b811a49e
--- /dev/null
+++ b/tests/ui/traits/object/no-incomplete-inference.current.stderr
@@ -0,0 +1,16 @@
+error[E0283]: type annotations needed
+  --> $DIR/no-incomplete-inference.rs:16:5
+   |
+LL |     impls_equals::<dyn Equals<u32>, _>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_equals`
+   |
+   = note: cannot satisfy `dyn Equals<u32>: Equals<_>`
+note: required by a bound in `impls_equals`
+  --> $DIR/no-incomplete-inference.rs:13:20
+   |
+LL | fn impls_equals<T: Equals<U> + ?Sized, U: ?Sized>() {}
+   |                    ^^^^^^^^^ required by this bound in `impls_equals`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/object/no-incomplete-inference.next.stderr b/tests/ui/traits/object/no-incomplete-inference.next.stderr
new file mode 100644
index 00000000000..3c6b811a49e
--- /dev/null
+++ b/tests/ui/traits/object/no-incomplete-inference.next.stderr
@@ -0,0 +1,16 @@
+error[E0283]: type annotations needed
+  --> $DIR/no-incomplete-inference.rs:16:5
+   |
+LL |     impls_equals::<dyn Equals<u32>, _>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_equals`
+   |
+   = note: cannot satisfy `dyn Equals<u32>: Equals<_>`
+note: required by a bound in `impls_equals`
+  --> $DIR/no-incomplete-inference.rs:13:20
+   |
+LL | fn impls_equals<T: Equals<U> + ?Sized, U: ?Sized>() {}
+   |                    ^^^^^^^^^ required by this bound in `impls_equals`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/object/no-incomplete-inference.rs b/tests/ui/traits/object/no-incomplete-inference.rs
new file mode 100644
index 00000000000..9ed8dd6c0b1
--- /dev/null
+++ b/tests/ui/traits/object/no-incomplete-inference.rs
@@ -0,0 +1,18 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+
+// Make sure that having an applicable user-written
+// and builtin impl is ambiguous.
+
+trait Equals<T: ?Sized> {}
+
+impl<T: ?Sized> Equals<T> for T {}
+
+fn impls_equals<T: Equals<U> + ?Sized, U: ?Sized>() {}
+
+fn main() {
+    impls_equals::<dyn Equals<u32>, _>();
+    //~^ ERROR type annotations needed
+}