diff options
| author | bors <bors@rust-lang.org> | 2024-02-10 07:15:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-10 07:15:15 +0000 |
| commit | 757b8efed44eacbbc6baf4a393f77d23d5be90c8 (patch) | |
| tree | 3d1898c476ccb02da378740f1440ebf590084fcb /compiler/rustc_ty_utils/src | |
| parent | 68125c72d389060fe9aaee8d87ebd834f417c9fc (diff) | |
| parent | 540be28f6c2571e7be3ab3936b62635fa0d3caf3 (diff) | |
| download | rust-757b8efed44eacbbc6baf4a393f77d23d5be90c8.tar.gz rust-757b8efed44eacbbc6baf4a393f77d23d5be90c8.zip | |
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*`.
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 9faad10dd14..eae80199ce5 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -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) |
