While a Swift protocol can have its async requirements satisfied
by a sync witness, this is not the case for ObjC protocols because
it is not just a calling convention difference.
Because every async ObjC function requirement in the protocol also
has a sibling that is sync, a sync witness might be trying
to conform to the sync version that takes a completion handler.
Without this change, we were seeing an issue where we would
consider both the async and sync versions of an ObjC requirement,
and accidentially choose the async version when the witness was
sync, and then raise an error about the typechecker's mistake.
Instead of raising an error, this change removes the ability for
the typechecker to even consider the errornous conformance.
resolves rdar://73326234
Our name lookup rules for the resolution of custom attributes don't
allow for them to find MainActor within the _Concurrency library.
Therefore, hardcode @MainActor to map to _Concurrency.MainActor.
While here, make sure we drop concurrency-specific attributes that
show up in Clang attributes when we aren't in concurrency mode.
The Clang swift_attr attribute allows C code to describe, via a Clang
attribute, the Swift attributes that should be applied to the given
declaration. When an
__attribute__((__swift_attr__("@tribute")))
occurs on a Clang declaration, parse the attribute within the string
literal as a Swift attribute, then attach that to the imported Swift
declaration.
Fixes rdar://70146633.
If a completion handler takes an error argument, then the non-error arguments are bridged and forwarded to
the continuation only on the happy path. Make sure we forward a copy so the retain level of the success values
remains balanced across both branches. Fixes rdar://72604599.
`_Nullable_result` indicates that a parameter of a completion handler
should be imported as optional when the completion handler can fail by
throwing an error.
Implements rdar://70108088.
Extend the set of completion-handler names we look for to infer an
`async` import of an Objective-C method, which includes:
* (with)CompletionBlock
* (with)reply
* (with)replyTo
both as parameter names and as base name suffixes.
The new `swift_async_name` attribute allows Clang declarations to specify
their Swift names only for `async` import, which may differ from those used
for importing as a completion handler.
Implements rdar://70111787.
When mirroring declarations from protocols, make sure to mirror for
all potential imported names. Otherwise, we might miss out on one or
the other of an async import or a completion-handler import of the
same method.
Fixes rdar://71429577.
An ObjC API maybe imported as async that had multiple non-error arguments to
its completion handler, which we treat in Swift as returning a tuple. Use a new
form of abstraction pattern to represent this return type, to maintain the
correct relation between individual tuple elements and the Clang block parameter
types they map to.
When a completion handler parameter has a selector piece that ends with
"WithCompletion(Handler)", prepend the text before that suffix to the
base name or previous argument label, as appropriate. This ensures that
we don't lose information from the name, particularly with delegate names.
The majority of support comes in the form of emitting partial
application forwarders for partial applications of async functions.
Such a partial application forwarder must take an async context which
has been partially populated at the apply site. It is responsible for
populating it "the rest of the way". To do so, like sync partial
application forwarders, it takes a second argument, its context, from
which it pulls the additional arguments which were capture at
partial_apply time.
The size of the async context that is passed to the forwarder, however,
can't be known at the apply site by simply looking at the signature of
the function to be applied (not even by looking at the size associated
with the function in the special async function pointer constant which
will soon be emitted). The reason is that there are an unknown (at the
apply site) number of additional arguments which will be filled by the
partial apply forwarder (and in the case of repeated partial
applications, further filled in incrementally at each level). To enable
this, there will always be a heap object for thick async functions.
These heap objects will always store the size of the async context to be
allocated as their first element. (Note that it may be possible to
apply the same optimization that was applied for thick sync functions
where a single refcounted object could be used as the context; doing so,
however, must be made to interact properly with the async context size
stored in the heap object.)
To continue to allow promoting thin async functions to thick async
functions without incurring a thunk, at the apply site, a null-check
will be performed on the context pointer. If it is null, then the async
context size will be determined based on the signature. (When async
function pointers become pointers to a constant with a size i32 and a
relative address to the underlying function, the size will be read from
that constant.) When it is not-null, the size will be pulled from the
first field of the context (which will in that case be cast to
<{%swift.refcounted, i32}>).
To facilitate sharing code and preserving the original structure of
emitPartialApplicationForwarder (which weighed in at roughly 700 lines
prior to this change), a new small class hierarchy, descending from
PartialApplicationForwarderEmission has been added, with subclasses for
the sync and async case. The shuffling of arguments into and out of the
final explosion that was being performed in the synchronous case has
been preserved there, though the arguments are added and removed through
a number of methods on the superclass with more descriptive names. That
was necessary to enable the async class to handle these different
flavors of parameters correctly.
To get some initial test coverage, the preexisting
IRGen/partial_apply.sil and IRGen/partial_apply_forwarder.sil tests have
been duplicated into the async folder. Those tests cases within these
files which happened to have been crashing have each been extracted into
its own runnable test that both verifies that the compiler does not
crash and also that the partial application forwarder behaves correctly.
The FileChecks in these tests are extremely minimal, providing only
enough information to be sure that arguments are in fact squeezed into
an async context.
Here, the following is implemented:
- Construction of SwiftContext struct with the fields needed for calling
functions.
- Allocating and deallocating these swift context via runtime calls
before calling async functions and after returning from them.
- Storing arguments (including bindings and the self parameter but not
including protocol fields for witness methods) and returns (both
direct and indirect).
- Calling async functions.
Additional things that still need to be done:
- protocol extension methods
- protocol witness methods
- storing yields
- partial applies
The Clang importer was filtering out cases where the same declaration
is imported twice under the same name, which can now happen when one
is synchronous and one is asynchronous. This happens when, e.g., an
Objective-C class provides both a completion-hander-based asynchronous
version and a synchronous version, and the Swift names line up after
the completion-handler parameter is dropped.
Stop filtering these out. Overload resolution is capable of handling
synchronous/asynchronous overloading based on context.
Infer @asyncHandler on a protocol methods that follow the delegate
convention of reporting that something happened via a "did" method, so
long as they also meet the constraints for an @asyncHandler method in
Swift. This enables inference of @asyncHandler for witnesses of these
methods.
Extend the check for completion handler parameters to also consider the
name of the parameter (not its argument label). If it's `completion` or
`completionHandler`, we have a completion handler. This extends our
API coverage for importing Objective-C methods with completion
handlers as 'async'.
When a given Objective-C method has a completion handler parameter
with an appropriate signature, import that Objective-C method as
async. For example, consider the following CloudKit API:
- (void)fetchShareParticipantWithUserRecordID:(CKRecordID
*)userRecordID
completionHandler:(void (^)(CKShareParticipant * _Nullable shareParticipant, NSError * _Nullable error))completionHandler;
With the experimental concurrency model, this would import as:
func fetchShareParticipant(withUserRecordID userRecordID: CKRecord.ID) async throws -> CKShare.Participant?
The compiler will be responsible for turning the caller's continuation
into a block to pass along to the completion handler. When the error
parameter of the completion handler is non-null, the async call
will result in that error being thrown. Otherwise, the other arguments
passed to that completion handler will be returned as the result of
the async call.
async versions of methods are imported alongside their
completion-handler versions, to maintain source compatibility with
existing code that provides a completion handler.
Note that this only covers the Clang importer portion of this task.
We noticed that Some tests using the clang importer sdk ended up using the CoreFoundation overlay built as part of
Swift instead of the mock one provided.
A @_fixed_layout protocol exposes its witness table layout to
clients, which prevents re-ordering of requirements or adding
new requiremenst with a default.
When library evolution is enabled, we still emit method
descriptors even for @_fixed_layout protocols; this allows a
previously-resilient protocol to become @_fixed_layout as long
as the published layout matches the resilient layout in all
previously-shipped versions of the library.
Detect that result type of the overload choice is l-value and preserve
that information through the forced unwrap operation so it's possible
to load the value implicitly during solution application.
Resolves: rdar://problem/61337704
When generic metadata for a class is requested in the same module where
the class is defined, rather than a call to the generic metadata
accessor or to a variant of typeForMangledNode, a call to a new
accessor--a canonical specialized generic metadata accessor--is emitted.
The new function is defined schematically as follows:
MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) {
(void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete)
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete)
...
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete)
auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`);
return {metadata, MetadataState::Complete};
}
where generic_argument_class(C<K>, N) denotes the Nth generic argument
which is both (1) itself a specialized generic type and is also (2) a
class. These calls to the specialized metadata accessors for these
related types ensure that all generic class types are registered with
the Objective-C runtime.
To enable these new canonical specialized generic metadata accessors,
metadata for generic classes is prespecialized as needed. So are the
metaclasses and the corresponding rodata.
Previously, the lazy objc naming hook was registered during process
execution when the first generic class metadata was instantiated. Since
that instantiation may occur "before process launch" (i.e. if the
generic metadata is prespecialized), the lazy naming hook is now
installed at process launch.
We could assume usr/include belongs to header search paths. If a header
is located in a deeper location inside this directory, we need to print
the additional path components.
rdar://60857172