Auto merge of #120712 - compiler-errors:async-closures-harmonize, r=oli-obk
Harmonize `AsyncFn` implementations, make async closures conditionally impl `Fn*` traits This PR implements several changes to the built-in and libcore-provided implementations of `Fn*` and `AsyncFn*` to address two problems: 1. async closures do not implement the `Fn*` family traits, leading to breakage: https://crater-reports.s3.amazonaws.com/pr-120361/index.html 2. *references* to async closures do not implement `AsyncFn*`, as a consequence of the existing blanket impls of the shape `AsyncFn for F where F: Fn, F::Output: Future`. In order to fix (1.), we implement `Fn` traits appropriately for async closures. It turns out that async closures can: * always implement `FnOnce`, meaning that they're drop-in compatible with `FnOnce`-bound combinators like `Option::map`. * conditionally implement `Fn`/`FnMut` if they have no captures, which means that existing usages of async closures should *probably* work without breakage (crater checking this: https://github.com/rust-lang/rust/pull/120712#issuecomment-1930587805). In order to fix (2.), we make all of the built-in callables implement `AsyncFn*` via built-in impls, and instead adjust the blanket impls for `AsyncFn*` provided by libcore to match the blanket impls for `Fn*`.
This commit is contained in:
commit
757b8efed4
21 changed files with 706 additions and 263 deletions
|
@ -278,6 +278,24 @@ fn resolve_associated_item<'tcx>(
|
|||
def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
args: rcvr_args,
|
||||
}),
|
||||
ty::CoroutineClosure(coroutine_closure_def_id, args) => {
|
||||
// When a coroutine-closure implements the `Fn` traits, then it
|
||||
// always dispatches to the `FnOnce` implementation. This is to
|
||||
// ensure that the `closure_kind` of the resulting closure is in
|
||||
// sync with the built-in trait implementations (since all of the
|
||||
// implementations return `FnOnce::Output`).
|
||||
if ty::ClosureKind::FnOnce == args.as_coroutine_closure().kind() {
|
||||
Some(Instance::new(coroutine_closure_def_id, args))
|
||||
} else {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id,
|
||||
target_kind: ty::ClosureKind::FnOnce,
|
||||
},
|
||||
args,
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => bug!(
|
||||
"no built-in definition for `{trait_ref}::{}` for non-fn type",
|
||||
tcx.item_name(trait_item_id)
|
||||
|
@ -306,6 +324,19 @@ fn resolve_associated_item<'tcx>(
|
|||
Some(Instance::new(coroutine_closure_def_id, args))
|
||||
}
|
||||
}
|
||||
ty::Closure(closure_def_id, args) => {
|
||||
let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
|
||||
Some(Instance::resolve_closure(
|
||||
tcx,
|
||||
closure_def_id,
|
||||
args,
|
||||
trait_closure_kind,
|
||||
))
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
args: rcvr_args,
|
||||
}),
|
||||
_ => bug!(
|
||||
"no built-in definition for `{trait_ref}::{}` for non-lending-closure type",
|
||||
tcx.item_name(trait_item_id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue