Skip to content

Commit 3ce263a

Browse files
committed
Improve importParameterType for method parameters
Adapt the helper for figuring out parameter types for functions with the code exclusive for figuring out method parameters. This includes special code for handling dictionary subscripts, error parameters and completion handlers. The function parameters behaviour should not be modified, since in order to import function parameters all of the new pieces of code should be skipped following the value of the flags passed into the helper. For method parameters, there is extensive changes, specially in the cases of importing Obj-C++ methods that use C++ types, which were supported for functions, but not so much for methods.
1 parent aabdff3 commit 3ce263a

File tree

2 files changed

+64
-59
lines changed

2 files changed

+64
-59
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,9 @@ getImportTypeKindForParam(const clang::ParmVarDecl *param) {
22442244
Optional<swift::Type> ClangImporter::Implementation::importParameterType(
22452245
const clang::ParmVarDecl *param, OptionalTypeKind OptionalityOfParam,
22462246
ImportTypeKind importKind, bool allowNSUIntegerAsInt,
2247+
bool isNSDictionarySubscriptGetter, bool paramIsError,
2248+
bool paramIsCompletionHandler,
2249+
Optional<unsigned> completionHandlerErrorParamIndex,
22472250
ArrayRef<GenericTypeParamDecl *> genericParams,
22482251
llvm::function_ref<void(Diagnostic &&)> paramAddDiag, bool &isInOut,
22492252
bool &isParamTypeImplicitlyUnwrapped) {
@@ -2305,10 +2308,41 @@ Optional<swift::Type> ClangImporter::Implementation::importParameterType(
23052308
isInOut = true;
23062309
}
23072310

2311+
// Special case for NSDictionary's subscript.
2312+
if (isNSDictionarySubscriptGetter && paramTy->isObjCIdType()) {
2313+
// Not using `getImportTypeAttrs()` is unprincipled but OK for this hack.
2314+
auto nsCopying = SwiftContext.getNSCopyingType();
2315+
if (!nsCopying)
2316+
return None;
2317+
2318+
swiftParamTy = ExistentialType::get(nsCopying);
2319+
if (OptionalityOfParam != OTK_None)
2320+
swiftParamTy = OptionalType::get(swiftParamTy);
2321+
2322+
isParamTypeImplicitlyUnwrapped =
2323+
OptionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
2324+
}
2325+
23082326
if (!swiftParamTy) {
2327+
bool sendableByDefault =
2328+
paramIsCompletionHandler &&
2329+
SwiftContext.LangOpts.hasFeature(Feature::SendableCompletionHandlers);
2330+
2331+
auto attrs = getImportTypeAttrs(param, /*isParam=*/true, sendableByDefault);
2332+
2333+
// If this is the throws error parameter, we don't need to convert any
2334+
// NSError** arguments to the sugared NSErrorPointer typealias form,
2335+
// because all that is done with it is retrieving the canonical
2336+
// type. Avoiding the sugar breaks a loop in Foundation caused by method
2337+
// on NSString that has an error parameter. FIXME: This is a work-around
2338+
// for the specific case when the throws conversion works, but is not
2339+
// sufficient if it fails. (The correct, overarching fix is ClangImporter
2340+
// being lazier.)
23092341
auto importedType =
23102342
importType(paramTy, importKind, paramAddDiag, allowNSUIntegerAsInt,
2311-
Bridgeability::Full, attrs, OptionalityOfParam);
2343+
Bridgeability::Full, attrs, OptionalityOfParam,
2344+
/*resugarNSErrorPointer=*/!paramIsError,
2345+
completionHandlerErrorParamIndex);
23122346
if (!importedType)
23132347
return None;
23142348

@@ -2380,7 +2414,11 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
23802414

23812415
auto swiftParamTy = importParameterType(
23822416
param, OptionalityOfParam, importKind, allowNSUIntegerAsInt,
2383-
genericParams, paramAddDiag, isInOut, isParamTypeImplicitlyUnwrapped);
2417+
/*isNSDictionarySubscriptGetter=*/false,
2418+
/*paramIsError=*/false,
2419+
/*paramIsCompletionHandler=*/false,
2420+
/*completionHandlerErrorParamIndex=*/None, genericParams, paramAddDiag,
2421+
isInOut, isParamTypeImplicitlyUnwrapped);
23842422
if (!swiftParamTy) {
23852423
addImportDiagnostic(param,
23862424
Diagnostic(diag::parameter_type_not_imported, param),
@@ -2931,8 +2969,6 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
29312969
OptionalTypeKind optionalityOfParam =
29322970
getParamOptionality(param, knownNonNull);
29332971

2934-
// Import the parameter type into Swift.
2935-
29362972
bool allowNSUIntegerAsIntInParam = isFromSystemModule;
29372973
if (allowNSUIntegerAsIntInParam) {
29382974
StringRef name;
@@ -2950,70 +2986,24 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
29502986

29512987
bool isInOut = false;
29522988
bool paramIsIUO = false;
2953-
2954-
Type swiftParamTy;
2955-
if (auto typedefType = dyn_cast<clang::TypedefType>(paramTy.getTypePtr())) {
2956-
if (isUnavailableInSwift(typedefType->getDecl())) {
2957-
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
2958-
// If this fails, it means that we need a stronger predicate for
2959-
// determining the relationship between an enum and typedef.
2960-
assert(clangEnum.getValue()->getIntegerType()->getCanonicalTypeInternal() ==
2961-
typedefType->getCanonicalTypeInternal());
2962-
if (auto swiftEnum = importDecl(*clangEnum, CurrentVersion)) {
2963-
swiftParamTy = cast<NominalTypeDecl>(swiftEnum)->getDeclaredType();
2964-
}
2965-
}
2966-
}
2967-
}
2968-
2969-
// Special case for NSDictionary's subscript.
2970-
if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
2971-
paramTy->isObjCIdType()) {
2972-
// Not using `getImportTypeAttrs()` is unprincipled but OK for this hack.
2973-
auto nsCopying = SwiftContext.getNSCopyingType();
2974-
if (!nsCopying)
2975-
return {Type(), false};
2976-
swiftParamTy = ExistentialType::get(nsCopying);
2977-
if (optionalityOfParam != OTK_None)
2978-
swiftParamTy = OptionalType::get(swiftParamTy);
2979-
2980-
paramIsIUO = optionalityOfParam == OTK_ImplicitlyUnwrappedOptional;
2981-
} else if (!swiftParamTy) {
2982-
bool sendableByDefault = paramIsCompletionHandler &&
2983-
SwiftContext.LangOpts.hasFeature(Feature::SendableCompletionHandlers);
2984-
2985-
// If this is the throws error parameter, we don't need to convert any
2986-
// NSError** arguments to the sugared NSErrorPointer typealias form,
2987-
// because all that is done with it is retrieving the canonical
2988-
// type. Avoiding the sugar breaks a loop in Foundation caused by method
2989-
// on NSString that has an error parameter. FIXME: This is a work-around
2990-
// for the specific case when the throws conversion works, but is not
2991-
// sufficient if it fails. (The correct, overarching fix is ClangImporter
2992-
// being lazier.)
2993-
auto importedParamType =
2994-
importType(paramTy, importKind, paramAddDiag,
2995-
allowNSUIntegerAsIntInParam, Bridgeability::Full,
2996-
getImportTypeAttrs(param, /*isParam=*/true,
2997-
sendableByDefault),
2998-
optionalityOfParam,
2999-
/*resugarNSErrorPointer=*/!paramIsError,
3000-
completionHandlerErrorParamIndex);
3001-
paramIsIUO = importedParamType.isImplicitlyUnwrapped();
3002-
swiftParamTy = importedParamType.getType();
3003-
}
2989+
auto swiftParamTy = importParameterType(
2990+
param, optionalityOfParam, importKind, allowNSUIntegerAsIntInParam,
2991+
kind == SpecialMethodKind::NSDictionarySubscriptGetter, paramIsError,
2992+
paramIsCompletionHandler, completionHandlerErrorParamIndex,
2993+
ArrayRef<GenericTypeParamDecl *>(), paramAddDiag, isInOut, paramIsIUO);
30042994
if (!swiftParamTy) {
30052995
addImportDiagnostic(param,
30062996
Diagnostic(diag::parameter_type_not_imported, param),
30072997
param->getSourceRange().getBegin());
30082998
return {Type(), false};
30092999
}
30103000

3011-
swiftParamTy = mapGenericArgs(origDC, dc, swiftParamTy);
3001+
swiftParamTy = mapGenericArgs(origDC, dc, *swiftParamTy);
30123002

30133003
// If this is the error parameter, remember it, but don't build it
30143004
// into the parameter type.
30153005
if (paramIsError) {
3016-
errorParamType = swiftParamTy->getCanonicalType();
3006+
errorParamType = (*swiftParamTy)->getCanonicalType();
30173007

30183008
// ...unless we're supposed to replace it with ().
30193009
if (errorInfo->ErrorParameterIsReplaced) {
@@ -3027,7 +3017,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
30273017
// type but don't build it into the parameter type.
30283018
if (isAsync && paramIsCompletionHandler) {
30293019
if (Type replacedSwiftResultTy =
3030-
decomposeCompletionHandlerType(swiftParamTy, *asyncInfo)) {
3020+
decomposeCompletionHandlerType(*swiftParamTy, *asyncInfo)) {
30313021
swiftResultTy = replacedSwiftResultTy;
30323022

30333023
// Import the original completion handler type without adjustments.
@@ -3052,7 +3042,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
30523042

30533043
// Set up the parameter info
30543044
auto paramInfo =
3055-
getParameterInfo(this, param, name, swiftParamTy, isInOut, paramIsIUO);
3045+
getParameterInfo(this, param, name, *swiftParamTy, isInOut, paramIsIUO);
30563046

30573047
// Determine whether we have a default argument.
30583048
if (kind == SpecialMethodKind::Regular ||

lib/ClangImporter/ImporterImpl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,18 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13721372
/// \param importType The kind of parameter import that is being performed.
13731373
/// \param allowNSUIntegerAsInt If true, NSUInteger will be import as Int
13741374
/// in certain contexts. If false, it will always be import as UInt.
1375+
/// \param isNSDictionarySubscriptGetter If true, the parameter is being
1376+
/// imported as part of an NSDictionary subscript getter. If false,
1377+
/// the parameter belongs to some other kind of method/function.
1378+
/// \param paramIsError If true, the parameter being imported is an NSError
1379+
/// parameter. If false, the parameter is not an error parameter.
1380+
/// \param paramIsCompletionHandler If true, the parameter being imported is
1381+
/// a completion handler. If false, the parameter is not a completion
1382+
/// handler.
1383+
/// \param completionHandlerErrorParamIndex If it contains a value, the value
1384+
/// indicates the index of the completion handler whose error
1385+
/// parameter is used to indicate throwing. If None, the function does
1386+
/// not have such parameter.
13751387
/// \param genericParams For C++ functions, an array of the generic type
13761388
/// parameters of the function. For the rest of cases, an empty array
13771389
/// can be provided.
@@ -1388,6 +1400,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13881400
Optional<swift::Type> importParameterType(
13891401
const clang::ParmVarDecl *param, OptionalTypeKind optionalityOfParam,
13901402
ImportTypeKind importType, bool allowNSUIntegerAsInt,
1403+
bool isNSDictionarySubscriptGetter, bool paramIsError,
1404+
bool paramIsCompletionHandler,
1405+
Optional<unsigned> completionHandlerErrorParamIndex,
13911406
ArrayRef<GenericTypeParamDecl *> genericParams,
13921407
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn,
13931408
bool &isInOut, bool &isParamTypeImplicitlyUnwrapped);

0 commit comments

Comments
 (0)