@@ -195,13 +195,18 @@ namespace {
195
195
ClangImporter::Implementation &Impl;
196
196
bool AllowNSUIntegerAsInt;
197
197
Bridgeability Bridging;
198
+ const clang::FunctionType *CompletionHandlerType;
199
+ Optional<unsigned > CompletionHandlerErrorParamIndex;
198
200
199
201
public:
200
202
SwiftTypeConverter (ClangImporter::Implementation &impl,
201
203
bool allowNSUIntegerAsInt,
202
- Bridgeability bridging)
204
+ Bridgeability bridging,
205
+ const clang::FunctionType *completionHandlerType,
206
+ Optional<unsigned > completionHandlerErrorParamIndex)
203
207
: Impl(impl), AllowNSUIntegerAsInt(allowNSUIntegerAsInt),
204
- Bridging (bridging) {}
208
+ Bridging (bridging), CompletionHandlerType(completionHandlerType),
209
+ CompletionHandlerErrorParamIndex(completionHandlerErrorParamIndex) {}
205
210
206
211
using TypeVisitor::Visit;
207
212
ImportResult Visit (clang::QualType type) {
@@ -612,8 +617,19 @@ namespace {
612
617
for (auto param = type->param_type_begin (),
613
618
paramEnd = type->param_type_end ();
614
619
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
+
615
631
auto swiftParamTy = Impl.importTypeIgnoreIUO (
616
- *param, ImportTypeKind::Parameter , AllowNSUIntegerAsInt, Bridging,
632
+ *param, paramImportKind , AllowNSUIntegerAsInt, Bridging,
617
633
OTK_Optional);
618
634
if (!swiftParamTy)
619
635
return Type ();
@@ -1191,6 +1207,7 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
1191
1207
case ImportTypeKind::Result:
1192
1208
case ImportTypeKind::AuditedResult:
1193
1209
case ImportTypeKind::Parameter:
1210
+ case ImportTypeKind::CompletionHandlerResultParameter:
1194
1211
case ImportTypeKind::CFRetainedOutParameter:
1195
1212
case ImportTypeKind::CFUnretainedOutParameter:
1196
1213
case ImportTypeKind::Property:
@@ -1218,6 +1235,7 @@ static bool isCFAudited(ImportTypeKind importKind) {
1218
1235
case ImportTypeKind::AuditedVariable:
1219
1236
case ImportTypeKind::AuditedResult:
1220
1237
case ImportTypeKind::Parameter:
1238
+ case ImportTypeKind::CompletionHandlerResultParameter:
1221
1239
case ImportTypeKind::CFRetainedOutParameter:
1222
1240
case ImportTypeKind::CFUnretainedOutParameter:
1223
1241
case ImportTypeKind::Property:
@@ -1520,7 +1538,8 @@ static ImportedType adjustTypeForConcreteImport(
1520
1538
ImportedType ClangImporter::Implementation::importType (
1521
1539
clang::QualType type, ImportTypeKind importKind, bool allowNSUIntegerAsInt,
1522
1540
Bridgeability bridging, OptionalTypeKind optionality,
1523
- bool resugarNSErrorPointer) {
1541
+ bool resugarNSErrorPointer,
1542
+ Optional<unsigned > completionHandlerErrorParamIndex) {
1524
1543
if (type.isNull ())
1525
1544
return {Type (), false };
1526
1545
@@ -1555,11 +1574,28 @@ ImportedType ClangImporter::Implementation::importType(
1555
1574
// If nullability is provided as part of the type, that overrides
1556
1575
// optionality provided externally.
1557
1576
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
+ }
1559
1593
}
1560
1594
1561
1595
// 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);
1563
1599
auto importResult = converter.Visit (type);
1564
1600
1565
1601
// Now fix up the type based on how we're concretely using it.
@@ -2085,13 +2121,7 @@ static Type decomposeCompletionHandlerType(
2085
2121
paramIdx == *info.completionHandlerErrorParamIndex ())
2086
2122
continue ;
2087
2123
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 ());
2095
2125
}
2096
2126
2097
2127
switch (resultTypeElts.size ()) {
@@ -2266,6 +2296,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2266
2296
}
2267
2297
2268
2298
// Special case for NSDictionary's subscript.
2299
+ ImportTypeKind importKind = ImportTypeKind::Parameter;
2269
2300
Type swiftParamTy;
2270
2301
bool paramIsIUO;
2271
2302
if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
@@ -2276,12 +2307,19 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2276
2307
2277
2308
paramIsIUO = optionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
2278
2309
} else {
2279
- ImportTypeKind importKind = ImportTypeKind::Parameter;
2280
2310
if (param->hasAttr <clang::CFReturnsRetainedAttr>())
2281
2311
importKind = ImportTypeKind::CFRetainedOutParameter;
2282
2312
else if (param->hasAttr <clang::CFReturnsNotRetainedAttr>())
2283
2313
importKind = ImportTypeKind::CFUnretainedOutParameter;
2284
2314
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
+
2285
2323
// If this is the throws error parameter, we don't need to convert any
2286
2324
// NSError** arguments to the sugared NSErrorPointer typealias form,
2287
2325
// because all that is done with it is retrieving the canonical
@@ -2293,7 +2331,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2293
2331
auto importedParamType =
2294
2332
importType (paramTy, importKind, allowNSUIntegerAsIntInParam,
2295
2333
Bridgeability::Full, optionalityOfParam,
2296
- /* resugarNSErrorPointer=*/ !paramIsError);
2334
+ /* resugarNSErrorPointer=*/ !paramIsError,
2335
+ completionHandlerErrorParamIndex);
2297
2336
paramIsIUO = importedParamType.isImplicitlyUnwrapped ();
2298
2337
swiftParamTy = importedParamType.getType ();
2299
2338
}
@@ -2321,7 +2360,14 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2321
2360
if (Type replacedSwiftResultTy =
2322
2361
decomposeCompletionHandlerType (swiftParamTy, *asyncInfo)) {
2323
2362
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 ();
2325
2371
continue ;
2326
2372
}
2327
2373
0 commit comments