@@ -195,13 +195,18 @@ namespace {
195195 ClangImporter::Implementation &Impl;
196196 bool AllowNSUIntegerAsInt;
197197 Bridgeability Bridging;
198+ const clang::FunctionType *CompletionHandlerType;
199+ Optional<unsigned > CompletionHandlerErrorParamIndex;
198200
199201 public:
200202 SwiftTypeConverter (ClangImporter::Implementation &impl,
201203 bool allowNSUIntegerAsInt,
202- Bridgeability bridging)
204+ Bridgeability bridging,
205+ const clang::FunctionType *completionHandlerType,
206+ Optional<unsigned > completionHandlerErrorParamIndex)
203207 : Impl(impl), AllowNSUIntegerAsInt(allowNSUIntegerAsInt),
204- Bridging (bridging) {}
208+ Bridging (bridging), CompletionHandlerType(completionHandlerType),
209+ CompletionHandlerErrorParamIndex(completionHandlerErrorParamIndex) {}
205210
206211 using TypeVisitor::Visit;
207212 ImportResult Visit (clang::QualType type) {
@@ -612,8 +617,17 @@ namespace {
612617 for (auto param = type->param_type_begin (),
613618 paramEnd = type->param_type_end ();
614619 param != paramEnd; ++param) {
620+ // Determine whether we have a result parameter of a completion
621+ // handler that can also express a thrown error.
622+ ImportTypeKind paramImportKind = ImportTypeKind::Parameter;
623+ unsigned paramIdx = param - type->param_type_begin ();
624+ if (type == CompletionHandlerType &&
625+ paramIdx != CompletionHandlerErrorParamIndex) {
626+ paramImportKind = ImportTypeKind::CompletionHandlerResultParameter;
627+ }
628+
615629 auto swiftParamTy = Impl.importTypeIgnoreIUO (
616- *param, ImportTypeKind::Parameter , AllowNSUIntegerAsInt, Bridging,
630+ *param, paramImportKind , AllowNSUIntegerAsInt, Bridging,
617631 OTK_Optional);
618632 if (!swiftParamTy)
619633 return Type ();
@@ -1191,6 +1205,7 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
11911205 case ImportTypeKind::Result:
11921206 case ImportTypeKind::AuditedResult:
11931207 case ImportTypeKind::Parameter:
1208+ case ImportTypeKind::CompletionHandlerResultParameter:
11941209 case ImportTypeKind::CFRetainedOutParameter:
11951210 case ImportTypeKind::CFUnretainedOutParameter:
11961211 case ImportTypeKind::Property:
@@ -1218,6 +1233,7 @@ static bool isCFAudited(ImportTypeKind importKind) {
12181233 case ImportTypeKind::AuditedVariable:
12191234 case ImportTypeKind::AuditedResult:
12201235 case ImportTypeKind::Parameter:
1236+ case ImportTypeKind::CompletionHandlerResultParameter:
12211237 case ImportTypeKind::CFRetainedOutParameter:
12221238 case ImportTypeKind::CFUnretainedOutParameter:
12231239 case ImportTypeKind::Property:
@@ -1520,7 +1536,8 @@ static ImportedType adjustTypeForConcreteImport(
15201536ImportedType ClangImporter::Implementation::importType (
15211537 clang::QualType type, ImportTypeKind importKind, bool allowNSUIntegerAsInt,
15221538 Bridgeability bridging, OptionalTypeKind optionality,
1523- bool resugarNSErrorPointer) {
1539+ bool resugarNSErrorPointer,
1540+ Optional<unsigned > completionHandlerErrorParamIndex) {
15241541 if (type.isNull ())
15251542 return {Type (), false };
15261543
@@ -1555,11 +1572,26 @@ ImportedType ClangImporter::Implementation::importType(
15551572 // If nullability is provided as part of the type, that overrides
15561573 // optionality provided externally.
15571574 if (auto nullability = type->getNullability (clangContext)) {
1558- optionality = translateNullability (*nullability);
1575+ bool stripNonResultOptionality =
1576+ importKind == ImportTypeKind::CompletionHandlerResultParameter;
1577+
1578+ optionality = translateNullability (*nullability, stripNonResultOptionality);
1579+ }
1580+
1581+ // If this is a completion handler parameter, record the function type whose
1582+ // parameters will act as the results of the completion handler.
1583+ const clang::FunctionType *completionHandlerType = nullptr ;
1584+ if (completionHandlerErrorParamIndex) {
1585+ if (auto blockPtrType = type->getAs <clang::BlockPointerType>()) {
1586+ completionHandlerType =
1587+ blockPtrType->getPointeeType ()->castAs <clang::FunctionType>();
1588+ }
15591589 }
15601590
15611591 // Perform abstract conversion, ignoring how the type is actually used.
1562- SwiftTypeConverter converter (*this , allowNSUIntegerAsInt, bridging);
1592+ SwiftTypeConverter converter (
1593+ *this , allowNSUIntegerAsInt, bridging,
1594+ completionHandlerType, completionHandlerErrorParamIndex);
15631595 auto importResult = converter.Visit (type);
15641596
15651597 // Now fix up the type based on how we're concretely using it.
@@ -2085,13 +2117,7 @@ static Type decomposeCompletionHandlerType(
20852117 paramIdx == *info.completionHandlerErrorParamIndex ())
20862118 continue ;
20872119
2088- // If there is an error parameter, remove nullability.
2089- Type paramType = param.getPlainType ();
2090- // TODO: Clang should gain a nullability form that overrides this.
2091- if (info.completionHandlerErrorParamIndex ())
2092- paramType = paramType->lookThroughAllOptionalTypes ();
2093-
2094- resultTypeElts.push_back (paramType);
2120+ resultTypeElts.push_back (param.getPlainType ());
20952121 }
20962122
20972123 switch (resultTypeElts.size ()) {
@@ -2266,6 +2292,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22662292 }
22672293
22682294 // Special case for NSDictionary's subscript.
2295+ ImportTypeKind importKind = ImportTypeKind::Parameter;
22692296 Type swiftParamTy;
22702297 bool paramIsIUO;
22712298 if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
@@ -2276,12 +2303,19 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22762303
22772304 paramIsIUO = optionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
22782305 } else {
2279- ImportTypeKind importKind = ImportTypeKind::Parameter;
22802306 if (param->hasAttr <clang::CFReturnsRetainedAttr>())
22812307 importKind = ImportTypeKind::CFRetainedOutParameter;
22822308 else if (param->hasAttr <clang::CFReturnsNotRetainedAttr>())
22832309 importKind = ImportTypeKind::CFUnretainedOutParameter;
22842310
2311+ // Figure out if this is a completion handler parameter whose error
2312+ // parameter is used to indicate throwing.
2313+ Optional<unsigned > completionHandlerErrorParamIndex;
2314+ if (paramIsCompletionHandler) {
2315+ completionHandlerErrorParamIndex =
2316+ asyncInfo->completionHandlerErrorParamIndex ();
2317+ }
2318+
22852319 // If this is the throws error parameter, we don't need to convert any
22862320 // NSError** arguments to the sugared NSErrorPointer typealias form,
22872321 // because all that is done with it is retrieving the canonical
@@ -2293,7 +2327,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22932327 auto importedParamType =
22942328 importType (paramTy, importKind, allowNSUIntegerAsIntInParam,
22952329 Bridgeability::Full, optionalityOfParam,
2296- /* resugarNSErrorPointer=*/ !paramIsError);
2330+ /* resugarNSErrorPointer=*/ !paramIsError,
2331+ completionHandlerErrorParamIndex);
22972332 paramIsIUO = importedParamType.isImplicitlyUnwrapped ();
22982333 swiftParamTy = importedParamType.getType ();
22992334 }
@@ -2321,7 +2356,14 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
23212356 if (Type replacedSwiftResultTy =
23222357 decomposeCompletionHandlerType (swiftParamTy, *asyncInfo)) {
23232358 swiftResultTy = replacedSwiftResultTy;
2324- completionHandlerType = swiftParamTy->getCanonicalType ();
2359+
2360+ // Import the original completion handler type without adjustments.
2361+ Type origSwiftParamTy = importType (
2362+ paramTy, importKind, allowNSUIntegerAsIntInParam,
2363+ Bridgeability::Full, optionalityOfParam,
2364+ /* resugarNSErrorPointer=*/ !paramIsError, None).getType ();
2365+ completionHandlerType = mapGenericArgs (origDC, dc, origSwiftParamTy)
2366+ ->getCanonicalType ();
23252367 continue ;
23262368 }
23272369
0 commit comments