We want SILGen to have a simplified view of its executor and know that whenever
one sees an Actor, it is an actual actor instead of a Builtin.Executor. This
just simplifies code. Also, we should eventually have an invariant that
Builtin.Executor should only be allowed in LoweredSIL after LowerHopToExecutor
has run. But that is a change for another day.
This is a follow-up to https://github.com/swiftlang/swift/pull/82085
which made it so async variant doesn't get `@Sendable` inferred because
the proposal specified that inference should happen only on completion
handler parameter type of a synchronous variant of an imported API.
This runs into implementation issues related to thunking in some
cases were async convention expects the type of a completion handler
to match exactly for both variants of the imported API.
Resolves: rdar://154695053
This lifts the check for the feature flag up into the `importParameterType`
from `importType` and means that completion handler type for `async` variant
is no longer gains `@Sendable` attribute.
Specifically, I taught SILGen how to emit an AST like the following:
```
(force_value_expr implicit type="nonisolated(nonsending) (Date?) async -> Void" implicit_iuo_unwrap
(open_existential_expr implicit type="(nonisolated(nonsending) (Date?) async -> Void)?"
(opaque_value_expr implicit type="AnyObject")
(declref_expr type="AnyObject" decl="test.(file).repro().anyObject@test.swift:6:7" function_ref=unapplied)
(optional_evaluation_expr type="(nonisolated(nonsending) (Date?) async -> Void)?"
(inject_into_optional type="(nonisolated(nonsending) (Date?) async -> Void)?"
(function_conversion_expr type="nonisolated(nonsending) (Date?) async -> Void"
(bind_optional_expr type="(Date?) async -> Void" depth=0
(dynamic_member_ref_expr type="((Date?) async -> Void)?" decl="__ObjC.(file).Foo.start(at:)"
(opaque_value_expr type="AnyObject"))))))))
```
Since we are emitting an objc async function, there isn't an extra implicit
parameter like if we were using a swift async function. So, I just reused code
that was already used locally to look through these sorts of conversions. I
just had to add to that code support for conversions that add
nonisolated(nonsending). Previously it only supported looking through global
actor conversions.
rdar://152596823
Type annotations for instruction operands are omitted, e.g.
```
%3 = struct $S(%1, %2)
```
Operand types are redundant anyway and were only used for sanity checking in the SIL parser.
But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:
* if the block with the definition appears after the block where the operand's instruction is located
* if a block or instruction is printed in isolation, e.g. in a debugger
The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
The reason why I am doing this is that the unlike the codegen for checked
continuation, the codegen for unchecked continuation uses a sendable value
instead of Any as the block storage which prevents me from being able to create
a dependency from a non-Sendable @out parameter to the block.
By changing to use Any consistently, we are able to take advantage of Any not
being sendable to properly propagate this information.
Use the `%target-swift-5.1-abi-triple` substitution to compile the tests for
deployment to the minimum OS versions required for use of _Concurrency APIs,
instead of disabling availability checking.
While printing them as `some P` makes sense in the AST since they
only ever appear at their definition point, in the body of a SIL
function, opaque parameter types can be referenced by various
instructions, like any other generic parameter type.
Instead of printing out `some P` or `<anonymous>` depending on
context, neither of which actually parsed, instead print them
with the canonical type `τ_d_i` notation. Since it's printed this
way in the generic parameter list as well, it parses back in.
Fixes rdar://problem/119823811.
For an isolated ObjC function that is not async, we
emit a hops around the call. But if that function
returns an autoreleased pointer, we need to ensure
we're retaining that pointer before hopping back
after the call. We weren't doing that in the case
of an autoreleased NSError:
```
%10 = alloc_stack $@sil_unmanaged Optional<NSError>
%19 = ... a bunch of steps to wrap up %10 ...
%20 = enum $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, #Optional.some!enumelt, %19 : $AutoreleasingUnsafeMutablePointer<Optional<NSError>>
hop_to_executor $MainActor
%26 = apply X(Y, %20) : $@convention(objc_method) (NSObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>) -> @autoreleased Optional<NSString>
hop_to_executor $Optional<Builtin.Executor>
// retain the autoreleased pointer written-out.
%28 = load [trivial] %10 : $*@sil_unmanaged Optional<NSError>
%29 = unmanaged_to_ref %28 : $@sil_unmanaged Optional<NSError> to $Optional<NSError>
%30 = copy_value %29 : $Optional<NSError>
assign %31 to %7 : $*Optional<NSError>
```
This patch sinks the hop emission after the call
so it happens after doing that copy.
rdar://114049646
when two objc async functions are composed with each other,
i.e., f(g()), then the clean-ups for g() would get emitted
at an unexpected time, namely, during the suspension for
the call to f(). This means that using a clean-up to emit
the executor-hop breadcrumb was incorrect. The hop could
appear between a get_async continuation and its matching
await_continuation, which is an unsupported nested suspension.
This commit fixes that by removing the use of the breadcrumb
clean-up in favor of providing that breadcrumb directly to
the result plan, so that it may be emitted later on when the
result plan sees fit.
Fixes rdar://91502776
This reverts commit 01d470ce32.
Just to be safe, I'm reverting this part of https://github.com/apple/swift/pull/41571
as well, until it can be reimplemented in light of issues where a hop
can appear between a get_continuation and an await_continuation
resolves rdar://91502776
This reverts commit afd26d3974 to solve
a critical miscompile caused by a hop_to_executor appearing between
a get_continuation and await_continuation instruction in SIL.
A reimplementation of SR-15703 will be forthcoming.
Fixes rdar://91502776
Since the clean-up is not unwind only, we can rely on the
clean-ups to be emitted on both result and throw paths.
This does slightly change when the hop_to_executor is emitted,
in those paths, but that shouldn't matter.
refactors solution for rdar://78982371
Previously, the function emitCBridgedToNativeValue handled three
situations around optionals:
- Bridged?, Native?
- Bridged, Native?
- Bridged, Native
Here, handling for the fourth case
- Bridged?, Native
is added.
To enable this, the number of Optional wrappings that the bridged type
has that the native type does not is passed in to the function. Then,
in the portions of the function where actual transformations are done,
the values are unwrapped an appropriate number of times. Mostly that
means force unwrapping N times before doing the transformation. In the
case of types that conform to _ObjectiveCBridgeable, however, it means
force unwrapping the value N-1 times after doing the transformation
because _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC
performs one layer of unwrapping itself.
rdar://81590807
Fix a miscompile where a foreign `async` call would fail to emit an
appropriate `hop_to_executor` instruction to hop back to the current
executor afterward, meaning that subsequent code would not execute on
the correct actor.
Fixes rdar://81468980.
Previously, SILGen assumed that a foreign function could either have a
foreign async convention or a foreign error convention, but if it had
both, the error would be subsumed into the completion. That resulted in
failures to emit code for async calls of functions like
```
- (BOOL)minimalWithError:(NSError* _Nullable*)error
completionHandler:(void (^ _Nonnull)(void))completionHandler;
```
Here, SILGen gains the ability to emit such functions. To enable that,
a few changes were required when both conventions are present:
- a separate argument for each convention is used
- the ResultPlan is a ForeignErrorResultPlan nesting a
ForeignAsyncResultPlan
- the continuation is always of the form UnsafeContinuation<_, Error>
regardless of whether the completion handler takes an error
- the foreign error block fills the continuation with the error that was
passed by reference out of the ObjC method call
- the foreign error block branches to the block containing the await
instruction
rdar://80704984
Previously, AbstractionPattern::getOpaque() was used for async
continuations. That was problematic for functions like
```objc
- (void)performVoid2VoidWithCompletion:(void (^ _Nonnull)(void (^ _Nonnull)(void)))completion;
```
whose completion takes a closure. Doing so resulted in attempting to
build a block to func thunk where one of the functions had an out
parameter.
Instead, use the AbstractionPattern(ty).
rdar://79383990
Current SILGen for objc continuations, can end the lifetime of args
before await_async_continuation.
This PR fixes it by extending the lifetime of the args until await_async_continuation
by creating copies. And then inserts manual cleanup with fix_lifetime + destroy
Fixes rdar://78982371
Import APIs with the `swift_async_error` attribute in `zero_argument` or `nonzero_argument`
modes by checking the corresponding boolean argument to indicate the error status, instead of
treating it as part of the result tuple. rdar://70594666
Plumb generic signatures through the codegen for invoking foreign APIs as async, so that we
correctly handle APIs declared on ObjC lightweight generic classes. rdar://74361267
The goal of doing this is to reduce the amount of boilerplate and repeated code w.r.t. Continuation. Having just added `resume()` in four places, I got the sense that there was a lot of common code that was being duplicated. I removed the Throwing variants of these types (they can be expressed as Continuation<T, E:Error> instead of ThrowingContinuation<E>) and I broke out a significant amount of common code between CheckedContinuation and UnsafeContinuation into an implementation-only protocol to avoid repeating it. D.R.Y.
This change resolves rdar://74154769.
The bridging code handles optional wrapping and unwrapping, but in cases where a nullable completion
callback argument did not need bridging, it would get short circuited out of the bridging code, and
did not get unwrapped. Fixes rdar://73798726
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.
The `try await` ordering is both easier to read and indicates the order
of operations better, because the suspension point occurs first and
then one can observe a thrown error.
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.
To manage code size in user binaries, we want to be able to implement common completion handler signatures in
the Swift runtime once. Using a different mangling for these lets us add new ones without clobbering symbols in
existing binaries.