about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-03-23 18:56:34 +0000
committerMichael Goulet <michael@errs.io>2025-03-24 16:57:06 +0000
commit251455bcc5b3652d2af2eed29a317d0afd907e48 (patch)
tree66ef213d53af02aa78d4edae26ed2042a821bb88
parent90f5eab952728ac6edcf529a171f7de5c25e5d49 (diff)
downloadrust-251455bcc5b3652d2af2eed29a317d0afd907e48.tar.gz
rust-251455bcc5b3652d2af2eed29a317d0afd907e48.zip
Allow WellFormed goals to be returned from relating in new solver
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs16
-rw-r--r--tests/ui/traits/next-solver/well-formed-in-relate.rs21
-rw-r--r--tests/ui/traits/next-solver/well-formed-in-relate.stderr27
3 files changed, 57 insertions, 7 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 0322c9e4ab0..7ef36d0e9ae 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -971,15 +971,17 @@ where
         rhs: T,
     ) -> Result<(), NoSolution> {
         let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
-        if cfg!(debug_assertions) {
-            for g in goals.iter() {
-                match g.predicate.kind().skip_binder() {
-                    ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {}
-                    p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
+        for &goal in goals.iter() {
+            let source = match goal.predicate.kind().skip_binder() {
+                ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
+                    GoalSource::TypeRelating
                 }
-            }
+                // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive?
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc,
+                p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
+            };
+            self.add_goal(source, goal);
         }
-        self.add_goals(GoalSource::TypeRelating, goals);
         Ok(())
     }
 
diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.rs b/tests/ui/traits/next-solver/well-formed-in-relate.rs
new file mode 100644
index 00000000000..eec1ddef228
--- /dev/null
+++ b/tests/ui/traits/next-solver/well-formed-in-relate.rs
@@ -0,0 +1,21 @@
+fn main() {
+    let x;
+    //~^ ERROR type annotations needed for `Map<_, _>`
+    higher_ranked();
+    x = unconstrained_map();
+}
+
+fn higher_ranked() where for<'a> &'a (): Sized {}
+
+struct Map<T, U> where T: Fn() -> U {
+    t: T,
+}
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+fn unconstrained_map<T: Fn() -> U, U>() -> <Map<T, U> as Mirror>::Assoc { todo!() }
diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.stderr b/tests/ui/traits/next-solver/well-formed-in-relate.stderr
new file mode 100644
index 00000000000..5294a072d31
--- /dev/null
+++ b/tests/ui/traits/next-solver/well-formed-in-relate.stderr
@@ -0,0 +1,27 @@
+error[E0283]: type annotations needed for `Map<_, _>`
+  --> $DIR/well-formed-in-relate.rs:2:9
+   |
+LL |     let x;
+   |         ^
+...
+LL |     x = unconstrained_map();
+   |         ------------------- type must be known at this point
+   |
+   = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`:
+           - impl<A, F> Fn<A> for &F
+             where A: Tuple, F: Fn<A>, F: ?Sized;
+           - impl<Args, F, A> Fn<Args> for Box<F, A>
+             where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
+note: required by a bound in `unconstrained_map`
+  --> $DIR/well-formed-in-relate.rs:21:25
+   |
+LL | fn unconstrained_map<T: Fn() -> U, U>() -> <Map<T, U> as Mirror>::Assoc { todo!() }
+   |                         ^^^^^^^^^ required by this bound in `unconstrained_map`
+help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let x: Map<T, U>;
+   |          +++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.