Rollup merge of #141359 - compiler-errors:async-fn-once, r=lcnr
Fix `FnOnce` impl for `AsyncFn`/`AsyncFnMut` self-borrowing closures in new solver This only affects closures that are "`AsyncFn`/`AsyncFnMut`" in their calling capability that are being called with the `FnOnce` trait. fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/217 r? lcnr
This commit is contained in:
commit
654b2f39f1
3 changed files with 21 additions and 8 deletions
|
|
@ -327,7 +327,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
// always be called once. It additionally implements `Fn`/`FnMut`
|
||||
// only if it has no upvars referencing the closure-env lifetime,
|
||||
// and if the closure kind permits it.
|
||||
if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
|
||||
if goal_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -841,16 +841,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
};
|
||||
|
||||
let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() {
|
||||
let (closure_def_id, found_args, has_self_borrows) = match *self_ty.kind() {
|
||||
ty::Closure(def_id, args) => {
|
||||
(def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None)
|
||||
(def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), false)
|
||||
}
|
||||
ty::CoroutineClosure(def_id, args) => (
|
||||
def_id,
|
||||
args.as_coroutine_closure()
|
||||
.coroutine_closure_sig()
|
||||
.map_bound(|sig| sig.tupled_inputs_ty),
|
||||
Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
|
||||
!args.as_coroutine_closure().tupled_upvars_ty().is_ty_var()
|
||||
&& args.as_coroutine_closure().has_self_borrows(),
|
||||
),
|
||||
_ => return None,
|
||||
};
|
||||
|
|
@ -884,10 +885,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// If the closure has captures, then perhaps the reason that the trait
|
||||
// is unimplemented is because async closures don't implement `Fn`/`FnMut`
|
||||
// if they have captures.
|
||||
if let Some(by_ref_captures) = by_ref_captures
|
||||
&& let ty::FnPtr(sig_tys, _) = by_ref_captures.kind()
|
||||
&& !sig_tys.skip_binder().output().is_unit()
|
||||
{
|
||||
if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce {
|
||||
let mut err = self.dcx().create_err(AsyncClosureNotFn {
|
||||
span: self.tcx.def_span(closure_def_id),
|
||||
kind: expected_kind.as_str(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
//@ edition:2021
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
fn call_once<F>(_: impl FnOnce() -> F) {}
|
||||
|
||||
fn main() {
|
||||
let mut i = 0;
|
||||
let c = async || {
|
||||
i += 1;
|
||||
};
|
||||
call_once(c);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue