@@ -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,19 @@ 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 (CompletionHandlerType &&
625+ Impl.getClangASTContext ().hasSameType (
626+ CompletionHandlerType, type) &&
627+ paramIdx != CompletionHandlerErrorParamIndex) {
628+ paramImportKind = ImportTypeKind::CompletionHandlerResultParameter;
629+ }
630+
615631 auto swiftParamTy = Impl.importTypeIgnoreIUO (
616- *param, ImportTypeKind::Parameter , AllowNSUIntegerAsInt, Bridging,
632+ *param, paramImportKind , AllowNSUIntegerAsInt, Bridging,
617633 OTK_Optional);
618634 if (!swiftParamTy)
619635 return Type ();
@@ -1191,6 +1207,7 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
11911207 case ImportTypeKind::Result:
11921208 case ImportTypeKind::AuditedResult:
11931209 case ImportTypeKind::Parameter:
1210+ case ImportTypeKind::CompletionHandlerResultParameter:
11941211 case ImportTypeKind::CFRetainedOutParameter:
11951212 case ImportTypeKind::CFUnretainedOutParameter:
11961213 case ImportTypeKind::Property:
@@ -1218,6 +1235,7 @@ static bool isCFAudited(ImportTypeKind importKind) {
12181235 case ImportTypeKind::AuditedVariable:
12191236 case ImportTypeKind::AuditedResult:
12201237 case ImportTypeKind::Parameter:
1238+ case ImportTypeKind::CompletionHandlerResultParameter:
12211239 case ImportTypeKind::CFRetainedOutParameter:
12221240 case ImportTypeKind::CFUnretainedOutParameter:
12231241 case ImportTypeKind::Property:
@@ -1520,7 +1538,8 @@ static ImportedType adjustTypeForConcreteImport(
15201538ImportedType ClangImporter::Implementation::importType (
15211539 clang::QualType type, ImportTypeKind importKind, bool allowNSUIntegerAsInt,
15221540 Bridgeability bridging, OptionalTypeKind optionality,
1523- bool resugarNSErrorPointer) {
1541+ bool resugarNSErrorPointer,
1542+ Optional<unsigned > completionHandlerErrorParamIndex) {
15241543 if (type.isNull ())
15251544 return {Type (), false };
15261545
@@ -1555,11 +1574,28 @@ ImportedType ClangImporter::Implementation::importType(
15551574 // If nullability is provided as part of the type, that overrides
15561575 // optionality provided externally.
15571576 if (auto nullability = type->getNullability (clangContext)) {
1558- optionality = translateNullability (*nullability);
1577+ bool stripNonResultOptionality =
1578+ importKind == ImportTypeKind::CompletionHandlerResultParameter;
1579+
1580+ optionality = translateNullability (*nullability, stripNonResultOptionality);
1581+ }
1582+
1583+ // If this is a completion handler parameter, record the function type whose
1584+ // parameters will act as the results of the completion handler.
1585+ const clang::FunctionType *completionHandlerType = nullptr ;
1586+ if (completionHandlerErrorParamIndex) {
1587+ if (auto blockPtrType = type->getAs <clang::BlockPointerType>()) {
1588+ completionHandlerType =
1589+ blockPtrType->getPointeeType ()->castAs <clang::FunctionType>();
1590+
1591+ type = clang::QualType (blockPtrType, 0 );
1592+ }
15591593 }
15601594
15611595 // Perform abstract conversion, ignoring how the type is actually used.
1562- SwiftTypeConverter converter (*this , allowNSUIntegerAsInt, bridging);
1596+ SwiftTypeConverter converter (
1597+ *this , allowNSUIntegerAsInt, bridging,
1598+ completionHandlerType, completionHandlerErrorParamIndex);
15631599 auto importResult = converter.Visit (type);
15641600
15651601 // Now fix up the type based on how we're concretely using it.
@@ -2085,13 +2121,7 @@ static Type decomposeCompletionHandlerType(
20852121 paramIdx == *info.completionHandlerErrorParamIndex ())
20862122 continue ;
20872123
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);
2124+ resultTypeElts.push_back (param.getPlainType ());
20952125 }
20962126
20972127 switch (resultTypeElts.size ()) {
@@ -2266,6 +2296,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22662296 }
22672297
22682298 // Special case for NSDictionary's subscript.
2299+ ImportTypeKind importKind = ImportTypeKind::Parameter;
22692300 Type swiftParamTy;
22702301 bool paramIsIUO;
22712302 if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
@@ -2276,12 +2307,19 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22762307
22772308 paramIsIUO = optionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
22782309 } else {
2279- ImportTypeKind importKind = ImportTypeKind::Parameter;
22802310 if (param->hasAttr <clang::CFReturnsRetainedAttr>())
22812311 importKind = ImportTypeKind::CFRetainedOutParameter;
22822312 else if (param->hasAttr <clang::CFReturnsNotRetainedAttr>())
22832313 importKind = ImportTypeKind::CFUnretainedOutParameter;
22842314
2315+ // Figure out if this is a completion handler parameter whose error
2316+ // parameter is used to indicate throwing.
2317+ Optional<unsigned > completionHandlerErrorParamIndex;
2318+ if (paramIsCompletionHandler) {
2319+ completionHandlerErrorParamIndex =
2320+ asyncInfo->completionHandlerErrorParamIndex ();
2321+ }
2322+
22852323 // If this is the throws error parameter, we don't need to convert any
22862324 // NSError** arguments to the sugared NSErrorPointer typealias form,
22872325 // because all that is done with it is retrieving the canonical
@@ -2293,7 +2331,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
22932331 auto importedParamType =
22942332 importType (paramTy, importKind, allowNSUIntegerAsIntInParam,
22952333 Bridgeability::Full, optionalityOfParam,
2296- /* resugarNSErrorPointer=*/ !paramIsError);
2334+ /* resugarNSErrorPointer=*/ !paramIsError,
2335+ completionHandlerErrorParamIndex);
22972336 paramIsIUO = importedParamType.isImplicitlyUnwrapped ();
22982337 swiftParamTy = importedParamType.getType ();
22992338 }
@@ -2321,7 +2360,14 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
23212360 if (Type replacedSwiftResultTy =
23222361 decomposeCompletionHandlerType (swiftParamTy, *asyncInfo)) {
23232362 swiftResultTy = replacedSwiftResultTy;
2324- completionHandlerType = swiftParamTy->getCanonicalType ();
2363+
2364+ // Import the original completion handler type without adjustments.
2365+ Type origSwiftParamTy = importType (
2366+ paramTy, importKind, allowNSUIntegerAsIntInParam,
2367+ Bridgeability::Full, optionalityOfParam,
2368+ /* resugarNSErrorPointer=*/ !paramIsError, None).getType ();
2369+ completionHandlerType = mapGenericArgs (origDC, dc, origSwiftParamTy)
2370+ ->getCanonicalType ();
23252371 continue ;
23262372 }
23272373
0 commit comments