Skip to content

[5.5] [SILGen] Handle foreign funcs with error and async conventions. #38861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

nate-chandler
Copy link
Contributor

@nate-chandler nate-chandler commented Aug 12, 2021

5.5 Summary: Fix compiler crashes during emission of calls-as-async to ObjC functions that take error out parameters.


Explanation: When an ObjC method is called-as-async from Swift, SILGen generates code to handle ObjC's conventions around error handling. For example, ObjC often communicates errors via an NSError or flag argument passed to the completion handler. ObjC may, however, also communicate an error via a NSError out parameter at the top level such as

- (BOOL)minimalWithError:(NSError* _Nullable*)error
         completionHandler:(void (^ _Nonnull)(void))completionHandler;

Previously, SILGen assumed that a foreign function could either have a foreign async convention or a foreign error convention, but not both. Consequently, SILGen failed when attempting to call-as-async that method.

Here, SILGen gains the ability to emit calls-as-async to such functions. To enable that, the ResultPlan for such calls is now a ForeignErrorResultPlan nesting a ForeignAsyncResultPlan. The ForeignAsyncResultPlan-created continuation used for the call is now always of the form UnsafeContinuation<_, Error> regardless of whether the ObjC method's completion has an error or flag argument. That in turn enables the foreign error block--which is branched to if the error out parameter/return value indicates an error--to fill that continuation with the error and then to branch to the block which awaits the fulfillment of the continuation.

Issue: rdar://80704984

Original PR: #38740

Testing: New regression tests, Swift CI

Reviewed by: Joe Groff

Risk: Low.

Scope: Limited to Swift import of ObjC methods as async functions.

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
@nate-chandler nate-chandler requested a review from a team as a code owner August 12, 2021 19:24
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please nominate

@nate-chandler nate-chandler merged commit 8d59fd0 into swiftlang:release/5.5 Aug 17, 2021
@nate-chandler nate-chandler deleted the cherrypick/rdar80704984/release/5.5 branch August 17, 2021 00:27
@AnthonyLatsis AnthonyLatsis added 🍒 release cherry pick Flag: Release branch cherry picks swift 5.5 labels Jan 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks swift 5.5
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants