Skip to content

Commit

Permalink
Rollup merge of rust-lang#109739 - compiler-errors:new-solver-closure…
Browse files Browse the repository at this point in the history
…-fnonce, r=lcnr

Closures always implement `FnOnce` in new solver

We should process `[closure]: FnOnce(Tys...) -> Ty` obligations *before* fallback and closure analysis. We can do this by taking advantage of the fact that `FnOnce` is always implemented by closures, even before we definitely know the closure kind.

Fixes compiler-errors/next-solver-hir-issues#15

r? `@oli-obk` (trying to spread the reviewer load for new trait solver prs, and this one is pretty self-contained, though feel free to reassign 😸)
  • Loading branch information
Dylan-DPC committed Mar 30, 2023
2 parents 6e2e602 + 177997e commit 65e99f0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()))))
}
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/traits/new-solver/closure-inference-guidance.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 65e99f0

Please sign in to comment.