@@ -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,17 @@ 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 (type == CompletionHandlerType &&
625
+ paramIdx != CompletionHandlerErrorParamIndex) {
626
+ paramImportKind = ImportTypeKind::CompletionHandlerResultParameter;
627
+ }
628
+
615
629
auto swiftParamTy = Impl.importTypeIgnoreIUO (
616
- *param, ImportTypeKind::Parameter , AllowNSUIntegerAsInt, Bridging,
630
+ *param, paramImportKind , AllowNSUIntegerAsInt, Bridging,
617
631
OTK_Optional);
618
632
if (!swiftParamTy)
619
633
return Type ();
@@ -1191,6 +1205,7 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
1191
1205
case ImportTypeKind::Result:
1192
1206
case ImportTypeKind::AuditedResult:
1193
1207
case ImportTypeKind::Parameter:
1208
+ case ImportTypeKind::CompletionHandlerResultParameter:
1194
1209
case ImportTypeKind::CFRetainedOutParameter:
1195
1210
case ImportTypeKind::CFUnretainedOutParameter:
1196
1211
case ImportTypeKind::Property:
@@ -1218,6 +1233,7 @@ static bool isCFAudited(ImportTypeKind importKind) {
1218
1233
case ImportTypeKind::AuditedVariable:
1219
1234
case ImportTypeKind::AuditedResult:
1220
1235
case ImportTypeKind::Parameter:
1236
+ case ImportTypeKind::CompletionHandlerResultParameter:
1221
1237
case ImportTypeKind::CFRetainedOutParameter:
1222
1238
case ImportTypeKind::CFUnretainedOutParameter:
1223
1239
case ImportTypeKind::Property:
@@ -1520,7 +1536,8 @@ static ImportedType adjustTypeForConcreteImport(
1520
1536
ImportedType ClangImporter::Implementation::importType (
1521
1537
clang::QualType type, ImportTypeKind importKind, bool allowNSUIntegerAsInt,
1522
1538
Bridgeability bridging, OptionalTypeKind optionality,
1523
- bool resugarNSErrorPointer) {
1539
+ bool resugarNSErrorPointer,
1540
+ Optional<unsigned > completionHandlerErrorParamIndex) {
1524
1541
if (type.isNull ())
1525
1542
return {Type (), false };
1526
1543
@@ -1555,11 +1572,26 @@ ImportedType ClangImporter::Implementation::importType(
1555
1572
// If nullability is provided as part of the type, that overrides
1556
1573
// optionality provided externally.
1557
1574
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
+ }
1559
1589
}
1560
1590
1561
1591
// 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);
1563
1595
auto importResult = converter.Visit (type);
1564
1596
1565
1597
// Now fix up the type based on how we're concretely using it.
@@ -2085,13 +2117,7 @@ static Type decomposeCompletionHandlerType(
2085
2117
paramIdx == *info.completionHandlerErrorParamIndex ())
2086
2118
continue ;
2087
2119
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 ());
2095
2121
}
2096
2122
2097
2123
switch (resultTypeElts.size ()) {
@@ -2266,6 +2292,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2266
2292
}
2267
2293
2268
2294
// Special case for NSDictionary's subscript.
2295
+ ImportTypeKind importKind = ImportTypeKind::Parameter;
2269
2296
Type swiftParamTy;
2270
2297
bool paramIsIUO;
2271
2298
if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
@@ -2276,12 +2303,19 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2276
2303
2277
2304
paramIsIUO = optionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
2278
2305
} else {
2279
- ImportTypeKind importKind = ImportTypeKind::Parameter;
2280
2306
if (param->hasAttr <clang::CFReturnsRetainedAttr>())
2281
2307
importKind = ImportTypeKind::CFRetainedOutParameter;
2282
2308
else if (param->hasAttr <clang::CFReturnsNotRetainedAttr>())
2283
2309
importKind = ImportTypeKind::CFUnretainedOutParameter;
2284
2310
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
+
2285
2319
// If this is the throws error parameter, we don't need to convert any
2286
2320
// NSError** arguments to the sugared NSErrorPointer typealias form,
2287
2321
// because all that is done with it is retrieving the canonical
@@ -2293,7 +2327,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2293
2327
auto importedParamType =
2294
2328
importType (paramTy, importKind, allowNSUIntegerAsIntInParam,
2295
2329
Bridgeability::Full, optionalityOfParam,
2296
- /* resugarNSErrorPointer=*/ !paramIsError);
2330
+ /* resugarNSErrorPointer=*/ !paramIsError,
2331
+ completionHandlerErrorParamIndex);
2297
2332
paramIsIUO = importedParamType.isImplicitlyUnwrapped ();
2298
2333
swiftParamTy = importedParamType.getType ();
2299
2334
}
@@ -2321,7 +2356,14 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
2321
2356
if (Type replacedSwiftResultTy =
2322
2357
decomposeCompletionHandlerType (swiftParamTy, *asyncInfo)) {
2323
2358
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 ();
2325
2367
continue ;
2326
2368
}
2327
2369
0 commit comments