Skip to content

Commit 7cd96ae

Browse files
Rollup merge of #109739 - compiler-errors:new-solver-closure-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 😸)
2 parents fbe7383 + 177997e commit 7cd96ae

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,20 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
214214
ty::Closure(_, substs) => {
215215
let closure_substs = substs.as_closure();
216216
match closure_substs.kind_ty().to_opt_closure_kind() {
217-
Some(closure_kind) if closure_kind.extends(goal_kind) => {}
218-
None => return Ok(None),
219-
_ => return Err(NoSolution),
217+
// If the closure's kind doesn't extend the goal kind,
218+
// then the closure doesn't implement the trait.
219+
Some(closure_kind) => {
220+
if !closure_kind.extends(goal_kind) {
221+
return Err(NoSolution);
222+
}
223+
}
224+
// Closure kind is not yet determined, so we return ambiguity unless
225+
// the expected kind is `FnOnce` as that is always implemented.
226+
None => {
227+
if goal_kind != ty::ClosureKind::FnOnce {
228+
return Ok(None);
229+
}
230+
}
220231
}
221232
Ok(Some(closure_substs.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
222233
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
fn foo(i: isize) -> isize { i + 1 }
5+
6+
fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
7+
8+
pub fn main() {
9+
let f = |i| foo(i);
10+
assert_eq!(apply(f, 2), 3);
11+
}

0 commit comments

Comments
 (0)