@@ -719,7 +719,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
719
719
SILValue resumeBuf;
720
720
SILValue continuation;
721
721
ExecutorBreadcrumb breadcrumb;
722
-
722
+
723
+ SILValue blockStorage;
724
+ CanType blockStorageTy;
725
+ CanType continuationTy;
726
+
723
727
public:
724
728
ForeignAsyncInitializationPlan (SILGenFunction &SGF, SILLocation loc,
725
729
const CalleeTypeInfo &calleeTypeInfo)
@@ -820,9 +824,6 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
820
824
continuation = SGF.B .createGetAsyncContinuationAddr (loc, resumeBuf,
821
825
calleeTypeInfo.substResultType , throws);
822
826
823
- SILValue blockStorage;
824
- CanType blockStorageTy;
825
- CanType continuationTy;
826
827
std::tie (blockStorage, blockStorageTy, continuationTy) =
827
828
emitBlockStorage (SGF, loc, throws);
828
829
@@ -907,65 +908,74 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
907
908
// (1) fulfill the unsafe continuation with the foreign error
908
909
// (2) branch to the await block
909
910
{
910
- // First, fulfill the unsafe continuation with the foreign error.
911
+ // First, fulfill the continuation with the foreign error.
911
912
// Currently, that block's code looks something like
912
913
// %foreignError = ... : $*Optional<NSError>
913
914
// %converter = function_ref _convertNSErrorToError(_:)
914
915
// %error = apply %converter(%foreignError)
915
916
// [... insert here ...]
916
917
// destroy_value %error
917
918
// destroy_value %foreignError
918
- // Insert code to fulfill it after the native %error is defined. That
919
- // code should structure the RawUnsafeContinuation (continuation) into
920
- // an appropriately typed UnsafeContinuation and then pass that together
921
- // with (a copy of) the error to
922
- // _resumeUnsafeThrowingContinuationWithError.
919
+ // Insert code to fulfill it after the native %error is defined. That
920
+ // code should load UnsafeContinuation (or CheckedContinuation
921
+ // depending on mode) and then pass that together with (a copy of) the
922
+ // error to _resume{Unsafe, Checked}ThrowingContinuationWithError.
923
923
// [foreign_error_block_with_foreign_async_convention]
924
924
SGF.B .setInsertionPoint (
925
925
++bridgedForeignError->getDefiningInstruction ()->getIterator ());
926
926
927
- // FIXME: this case is not respecting checked bridging, and it's a
928
- // great candidate for that. This situation comes up when bridging
929
- // to an ObjC completion-handler method that returns a bool. It seems
930
- // that bool indicates whether the handler was invoked. If it was not
931
- // then it writes out an error. Here for the unsafe bridging, we're
932
- // invoking the continuation by re-wrapping it in an
933
- // UnsafeContinuation<_, Error> and then immediately calling its
934
- // resume(throwing: error) method. For a checked bridging scenario, we
935
- // would need to use a copy of the original CheckedContinuation that
936
- // was passed to the callee. Whether that's by invoking the block
937
- // ourselves, or just invoking the CheckedContinuation.
938
-
939
- auto continuationDecl = ctx.getUnsafeContinuationDecl ();
940
- auto errorTy = ctx.getErrorExistentialType ();
941
- auto continuationBGT =
942
- BoundGenericType::get (continuationDecl, Type (),
943
- {calleeTypeInfo.substResultType , errorTy});
927
+ bool checkedBridging = ctx.LangOpts .UseCheckedAsyncObjCBridging ;
928
+
944
929
auto env = SGF.F .getGenericEnvironment ();
945
930
auto sig = env ? env->getGenericSignature ().getCanonicalSignature ()
946
931
: CanGenericSignature ();
947
- auto mappedContinuationTy =
948
- continuationBGT->mapTypeOutOfContext ()->getReducedType (sig);
932
+
933
+ // Load unsafe or checked continuation from the block storage
934
+ // and call _resume{Unsafe, Checked}ThrowingContinuationWithError.
935
+
936
+ SILValue continuationAddr =
937
+ SGF.B .createProjectBlockStorage (loc, blockStorage);
938
+
939
+ ManagedValue continuation;
940
+ if (checkedBridging) {
941
+ FormalEvaluationScope scope (SGF);
942
+
943
+ auto underlyingValueTy =
944
+ OpenedArchetypeType::get (ctx.TheAnyType , sig);
945
+
946
+ auto underlyingValueAddr = SGF.emitOpenExistential (
947
+ loc, ManagedValue::forTrivialAddressRValue (continuationAddr),
948
+ SGF.getLoweredType (underlyingValueTy), AccessKind::Read);
949
+
950
+ continuation = SGF.B .createUncheckedAddrCast (
951
+ loc, underlyingValueAddr,
952
+ SILType::getPrimitiveAddressType (continuationTy));
953
+ } else {
954
+ auto continuationVal = SGF.B .createLoad (
955
+ loc, continuationAddr, LoadOwnershipQualifier::Trivial);
956
+ continuation =
957
+ ManagedValue::forObjectRValueWithoutOwnership (continuationVal);
958
+ }
959
+
960
+ auto mappedOutContinuationTy =
961
+ continuationTy->mapTypeOutOfContext ()->getReducedType (sig);
949
962
auto resumeType =
950
- cast<BoundGenericType>(mappedContinuationTy).getGenericArgs ()[0 ];
951
- auto continuationTy = continuationBGT->getCanonicalType ();
963
+ cast<BoundGenericType>(mappedOutContinuationTy).getGenericArgs ()[0 ];
952
964
953
965
auto errorIntrinsic =
954
- SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
966
+ checkedBridging
967
+ ? SGF.SGM .getResumeCheckedThrowingContinuationWithError ()
968
+ : SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
969
+
955
970
Type replacementTypes[] = {
956
971
SGF.F .mapTypeIntoContext (resumeType)->getCanonicalType ()};
957
972
auto subs = SubstitutionMap::get (errorIntrinsic->getGenericSignature (),
958
973
replacementTypes,
959
974
ArrayRef<ProtocolConformanceRef>{});
960
- auto wrappedContinuation = SGF.B .createStruct (
961
- loc, SILType::getPrimitiveObjectType (continuationTy),
962
- {continuation});
963
975
964
- auto continuationMV = ManagedValue::forObjectRValueWithoutOwnership (
965
- SILValue (wrappedContinuation));
966
976
SGF.emitApplyOfLibraryIntrinsic (
967
977
loc, errorIntrinsic, subs,
968
- {continuationMV ,
978
+ {continuation ,
969
979
SGF.B .copyOwnedObjectRValue (loc, bridgedForeignError,
970
980
ManagedValue::ScopeKind::Lexical)},
971
981
SGFContext ());
0 commit comments