Skip to content

[5.5] [SILGen] Handled transforming Bridged? -> Swift. #38862

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 crash for called-as-async ObjC methods whose completions take complex optional types that get unwrapped by Swift.


Explanation: When an ObjC method is called-as-async from Swift, SILGen creates a completion handler to pass to the ObjC method. That completion handler is sometimes responsible for unwrapping Optionals that ObjC passes in. To do that unwrapping, a common utility is used. That common utility needs to know how to deal with various cases of Optional-ness of the source/bridged/ObjC type and the target/native/Swift type.

Previously, that utility knew how to deal with three of the four cases of Optional-ness: (1) Optional<Bridged> -> Optional<Native>, (2) Bridged -> Optional<Native>, (3) Bridged -> Native. It didn't, however, handle the other case: (4) Optional<Bridged> -> Native. Consequently, SILGen failed to generate code for calling-as-async methods like the following:

typedef NSString *Flavor NS_EXTENSIBLE_STRING_ENUM;
- (void)getIceCreamFlavorWithCompletionHandler:(void (^)(NSError * __nullable error, Flavor __nullable flavor))completionHandler;
- (void)badWithCompletionHandler:(void (^)(void (^ _Nullable)(void), NSError * _Nullable, BOOL))completionHandler  __attribute__((swift_async_error(zero_argument, 3)));

Here, handling for that fourth case is added. The number of Optional wrappings that the bridged type has that the native type does not is passed in to the utility. When the utility recurs, it increments the number as appropriate. Then, in the portions of the function where 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. As a side note, the reason why this hadn't been more of a problem is because many handlers use types which conform to ObjectiveCBridgeable and as such were already unwrapped.

Issue: rdar://80704382

Original PR: #38773

Testing: New regression tests, Swift CI

Reviewed by: Joe Groff

Risk: Low.

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

@nate-chandler nate-chandler requested a review from a team as a code owner August 12, 2021 20:50
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please nominate

@nate-chandler nate-chandler force-pushed the cherrypick/rdar81590807/release/5.5 branch from 93a8db1 to 547297d Compare August 12, 2021 21:26
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

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
The underlying problem was fixed by the change for rdar://81590807 .
Add tests for the specific case that was originally reported.

rdar://80704382
@nate-chandler nate-chandler force-pushed the cherrypick/rdar81590807/release/5.5 branch from 547297d to e99cbaf Compare August 17, 2021 00:36
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler nate-chandler merged commit a44d790 into swiftlang:release/5.5 Aug 17, 2021
@AnthonyLatsis AnthonyLatsis added 🍒 release cherry pick Flag: Release branch cherry picks swift 5.5 labels Jan 8, 2023
@nate-chandler nate-chandler deleted the cherrypick/rdar81590807/release/5.5 branch July 5, 2023 23:30
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