diff options
| author | Michael Goulet <michael@errs.io> | 2023-03-30 12:42:20 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-30 12:42:20 -0700 |
| commit | 7cd96ae2d7b596a95f53e3edabed589b899e5407 (patch) | |
| tree | 3ffe8d58607b409032fffb1e179ab8f639f48485 | |
| parent | fbe738345cfe845f0d3b7b0961258187c3d26550 (diff) | |
| parent | 177997e3833d48973e7856e14f2935340b1862f1 (diff) | |
| download | rust-7cd96ae2d7b596a95f53e3edabed589b899e5407.tar.gz rust-7cd96ae2d7b596a95f53e3edabed589b899e5407.zip | |
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 😸)
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs | 17 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/closure-inference-guidance.rs | 11 |
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); +} |
