about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs17
-rw-r--r--tests/ui/traits/new-solver/closure-inference-guidance.rs11
2 files changed, 25 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 9817186b874..fcb965dd725 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -214,9 +214,20 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         ty::Closure(_, substs) => {
             let closure_substs = substs.as_closure();
             match closure_substs.kind_ty().to_opt_closure_kind() {
-                Some(closure_kind) if closure_kind.extends(goal_kind) => {}
-                None => return Ok(None),
-                _ => return Err(NoSolution),
+                // If the closure's kind doesn't extend the goal kind,
+                // then the closure doesn't implement the trait.
+                Some(closure_kind) => {
+                    if !closure_kind.extends(goal_kind) {
+                        return Err(NoSolution);
+                    }
+                }
+                // Closure kind is not yet determined, so we return ambiguity unless
+                // the expected kind is `FnOnce` as that is always implemented.
+                None => {
+                    if goal_kind != ty::ClosureKind::FnOnce {
+                        return Ok(None);
+                    }
+                }
             }
             Ok(Some(closure_substs.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
         }
diff --git a/tests/ui/traits/new-solver/closure-inference-guidance.rs b/tests/ui/traits/new-solver/closure-inference-guidance.rs
new file mode 100644
index 00000000000..d2ad0cc0316
--- /dev/null
+++ b/tests/ui/traits/new-solver/closure-inference-guidance.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn foo(i: isize) -> isize { i + 1 }
+
+fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
+
+pub fn main() {
+    let f = |i| foo(i);
+    assert_eq!(apply(f, 2), 3);
+}