@@ -203,6 +203,7 @@ AbstractionPattern::getOptional(AbstractionPattern object) {
203203 case Kind::PartialCurriedCXXOperatorMethodType:
204204 case Kind::OpaqueFunction:
205205 case Kind::OpaqueDerivativeFunction:
206+ case Kind::ObjCCompletionHandlerArgumentsType:
206207 llvm_unreachable (" cannot add optionality to non-type abstraction" );
207208 case Kind::Opaque:
208209 return AbstractionPattern::getOpaque ();
@@ -310,6 +311,7 @@ bool AbstractionPattern::matchesTuple(CanTupleType substType) {
310311 return true ;
311312 case Kind::Tuple:
312313 return getNumTupleElements_Stored () == substType->getNumElements ();
314+ case Kind::ObjCCompletionHandlerArgumentsType:
313315 case Kind::ClangType:
314316 case Kind::Type:
315317 case Kind::Discard: {
@@ -399,6 +401,19 @@ AbstractionPattern::getTupleElementType(unsigned index) const {
399401 return AbstractionPattern::getOpaque ();
400402 return AbstractionPattern (getGenericSignature (),
401403 getCanTupleElementType (getType (), index));
404+
405+ case Kind::ObjCCompletionHandlerArgumentsType: {
406+ // Match up the tuple element with the parameter from the Clang block type,
407+ // skipping the error parameter index if any.
408+ auto callback = cast<clang::FunctionProtoType>(getClangType ());
409+ auto errorIndex = getEncodedForeignInfo ()
410+ .getAsyncCompletionHandlerErrorParamIndex ();
411+ unsigned paramIndex = index + (errorIndex && index >= *errorIndex);
412+ return AbstractionPattern (getGenericSignature (),
413+ getCanTupleElementType (getType (), index),
414+ callback->getParamType (paramIndex).getTypePtr ());
415+ }
416+
402417 }
403418 llvm_unreachable (" bad kind" );
404419}
@@ -465,6 +480,7 @@ AbstractionPattern AbstractionPattern::getFunctionResultType() const {
465480 switch (getKind ()) {
466481 case Kind::Invalid:
467482 llvm_unreachable (" querying invalid abstraction pattern!" );
483+ case Kind::ObjCCompletionHandlerArgumentsType:
468484 case Kind::Tuple:
469485 llvm_unreachable (" abstraction pattern for tuple cannot be function" );
470486 case Kind::Opaque:
@@ -524,25 +540,45 @@ AbstractionPattern AbstractionPattern::getFunctionResultType() const {
524540 ->getPointeeType ()
525541 ->getAs <clang::FunctionProtoType>();
526542
527- // The result is the first non-error argument to the callback.
528- unsigned callbackResultIndex = 0 ;
529- if (auto callbackErrorIndex = getEncodedForeignInfo ()
530- .getAsyncCompletionHandlerErrorParamIndex ()) {
531- if (*callbackErrorIndex == 0 ) {
532- callbackResultIndex = 1 ;
533- }
543+ // The result comprises the non-error argument(s) to the callback, if
544+ // any.
545+
546+ auto callbackErrorIndex = getEncodedForeignInfo ()
547+ .getAsyncCompletionHandlerErrorParamIndex ();
548+ assert ((!callbackErrorIndex.hasValue ()
549+ || callbackParamTy->getNumParams () > *callbackErrorIndex)
550+ && " completion handler has invalid error param index?!" );
551+ unsigned numNonErrorParams
552+ = callbackParamTy->getNumParams () - callbackErrorIndex.hasValue ();
553+
554+ switch (numNonErrorParams) {
555+ case 0 :
556+ // If there are no result arguments, then the imported result type is
557+ // Void, with no interesting abstraction properties.
558+ return AbstractionPattern (TupleType::getEmpty (getType ()->getASTContext ()));
559+
560+ case 1 : {
561+ // If there's a single argument, abstract it according to its formal type
562+ // in the ObjC signature.
563+ unsigned callbackResultIndex
564+ = callbackErrorIndex && *callbackErrorIndex == 0 ;
565+ auto clangResultType = callbackParamTy
566+ ->getParamType (callbackResultIndex)
567+ .getTypePtr ();
568+
569+ return AbstractionPattern (getGenericSignatureForFunctionComponent (),
570+ getResultType (getType ()), clangResultType);
534571 }
535-
536- const clang::Type *clangResultType = nullptr ;
537- if (callbackResultIndex < callbackParamTy->getNumParams ()) {
538- clangResultType = callbackParamTy->getParamType (callbackResultIndex)
539- .getTypePtr ();
540- } else {
541- clangResultType = getObjCMethod ()->getASTContext ().VoidTy .getTypePtr ();
572+
573+ default :
574+ // If there are multiple results, we have a special abstraction pattern
575+ // form to represent the mapping from block parameters to tuple elements
576+ // in the return type.
577+ return AbstractionPattern::getObjCCompletionHandlerArgumentsType (
578+ getGenericSignatureForFunctionComponent (),
579+ getResultType (getType ()), callbackParamTy,
580+ getEncodedForeignInfo ());
542581 }
543-
544- return AbstractionPattern (getGenericSignatureForFunctionComponent (),
545- getResultType (getType ()), clangResultType);
546582 }
547583
548584 return AbstractionPattern (getGenericSignatureForFunctionComponent (),
@@ -594,6 +630,7 @@ AbstractionPattern::getObjCMethodAsyncCompletionHandlerType(
594630 case Kind::CurriedCFunctionAsMethodType:
595631 case Kind::CurriedCXXMethodType:
596632 case Kind::CurriedCXXOperatorMethodType:
633+ case Kind::ObjCCompletionHandlerArgumentsType:
597634 swift_unreachable (" not appropriate for this kind" );
598635 }
599636}
@@ -791,6 +828,7 @@ AbstractionPattern AbstractionPattern::getOptionalObjectType() const {
791828 case Kind::Tuple:
792829 case Kind::OpaqueFunction:
793830 case Kind::OpaqueDerivativeFunction:
831+ case Kind::ObjCCompletionHandlerArgumentsType:
794832 llvm_unreachable (" pattern for function or tuple cannot be for optional" );
795833
796834 case Kind::Opaque:
@@ -837,6 +875,7 @@ AbstractionPattern AbstractionPattern::getReferenceStorageReferentType() const {
837875 case Kind::Tuple:
838876 case Kind::OpaqueFunction:
839877 case Kind::OpaqueDerivativeFunction:
878+ case Kind::ObjCCompletionHandlerArgumentsType:
840879 return *this ;
841880 case Kind::Type:
842881 return AbstractionPattern (getGenericSignature (),
@@ -897,12 +936,15 @@ void AbstractionPattern::print(raw_ostream &out) const {
897936 case Kind::CurriedCFunctionAsMethodType:
898937 case Kind::PartialCurriedCFunctionAsMethodType:
899938 case Kind::CFunctionAsMethodType:
939+ case Kind::ObjCCompletionHandlerArgumentsType:
900940 out << (getKind () == Kind::ClangType
901941 ? " AP::ClangType(" :
902942 getKind () == Kind::CurriedCFunctionAsMethodType
903943 ? " AP::CurriedCFunctionAsMethodType(" :
904944 getKind () == Kind::PartialCurriedCFunctionAsMethodType
905- ? " AP::PartialCurriedCFunctionAsMethodType("
945+ ? " AP::PartialCurriedCFunctionAsMethodType(" :
946+ getKind () == Kind::ObjCCompletionHandlerArgumentsType
947+ ? " AP::ObjCCompletionHandlerArgumentsType("
906948 : " AP::CFunctionAsMethodType(" );
907949 if (auto sig = getGenericSignature ()) {
908950 sig->print (out);
@@ -922,6 +964,12 @@ void AbstractionPattern::print(raw_ostream &out) const {
922964 out << " static" ;
923965 }
924966 }
967+ if (hasStoredForeignInfo ()) {
968+ if (auto errorIndex
969+ = getEncodedForeignInfo ().getAsyncCompletionHandlerErrorParamIndex ()){
970+ out << " , errorParamIndex=" << *errorIndex;
971+ }
972+ }
925973 out << " )" ;
926974 return ;
927975 case Kind::CXXMethodType:
@@ -1069,6 +1117,9 @@ const {
10691117 case Kind::OpaqueDerivativeFunction:
10701118 llvm_unreachable (" should not have an opaque derivative function pattern "
10711119 " matching a struct/enum type" );
1120+ case Kind::ObjCCompletionHandlerArgumentsType:
1121+ llvm_unreachable (" should not have a completion handler argument pattern "
1122+ " matching a struct/enum type" );
10721123 case Kind::PartialCurriedObjCMethodType:
10731124 case Kind::CurriedObjCMethodType:
10741125 case Kind::PartialCurriedCFunctionAsMethodType:
0 commit comments