@@ -719,7 +719,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
719719 SILValue resumeBuf;
720720 SILValue continuation;
721721 ExecutorBreadcrumb breadcrumb;
722-
722+
723+ SILValue blockStorage;
724+ CanType blockStorageTy;
725+ CanType continuationTy;
726+
723727public:
724728 ForeignAsyncInitializationPlan (SILGenFunction &SGF, SILLocation loc,
725729 const CalleeTypeInfo &calleeTypeInfo)
@@ -820,9 +824,6 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
820824 continuation = SGF.B .createGetAsyncContinuationAddr (loc, resumeBuf,
821825 calleeTypeInfo.substResultType , throws);
822826
823- SILValue blockStorage;
824- CanType blockStorageTy;
825- CanType continuationTy;
826827 std::tie (blockStorage, blockStorageTy, continuationTy) =
827828 emitBlockStorage (SGF, loc, throws);
828829
@@ -907,65 +908,74 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
907908 // (1) fulfill the unsafe continuation with the foreign error
908909 // (2) branch to the await block
909910 {
910- // First, fulfill the unsafe continuation with the foreign error.
911+ // First, fulfill the continuation with the foreign error.
911912 // Currently, that block's code looks something like
912913 // %foreignError = ... : $*Optional<NSError>
913914 // %converter = function_ref _convertNSErrorToError(_:)
914915 // %error = apply %converter(%foreignError)
915916 // [... insert here ...]
916917 // destroy_value %error
917918 // 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.
923923 // [foreign_error_block_with_foreign_async_convention]
924924 SGF.B .setInsertionPoint (
925925 ++bridgedForeignError->getDefiningInstruction ()->getIterator ());
926926
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+
944929 auto env = SGF.F .getGenericEnvironment ();
945930 auto sig = env ? env->getGenericSignature ().getCanonicalSignature ()
946931 : 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);
949962 auto resumeType =
950- cast<BoundGenericType>(mappedContinuationTy).getGenericArgs ()[0 ];
951- auto continuationTy = continuationBGT->getCanonicalType ();
963+ cast<BoundGenericType>(mappedOutContinuationTy).getGenericArgs ()[0 ];
952964
953965 auto errorIntrinsic =
954- SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
966+ checkedBridging
967+ ? SGF.SGM .getResumeCheckedThrowingContinuationWithError ()
968+ : SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
969+
955970 Type replacementTypes[] = {
956971 SGF.F .mapTypeIntoContext (resumeType)->getCanonicalType ()};
957972 auto subs = SubstitutionMap::get (errorIntrinsic->getGenericSignature (),
958973 replacementTypes,
959974 ArrayRef<ProtocolConformanceRef>{});
960- auto wrappedContinuation = SGF.B .createStruct (
961- loc, SILType::getPrimitiveObjectType (continuationTy),
962- {continuation});
963975
964- auto continuationMV = ManagedValue::forObjectRValueWithoutOwnership (
965- SILValue (wrappedContinuation));
966976 SGF.emitApplyOfLibraryIntrinsic (
967977 loc, errorIntrinsic, subs,
968- {continuationMV ,
978+ {continuation ,
969979 SGF.B .copyOwnedObjectRValue (loc, bridgedForeignError,
970980 ManagedValue::ScopeKind::Lexical)},
971981 SGFContext ());
0 commit comments