Skip to content

Commit 47e4ab2

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 f014338 commit 47e4ab2

File tree

2 files changed

+67
-60
lines changed

2 files changed

+67
-60
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,10 @@ getImportTypeKindForParam(const clang::ParmVarDecl *param) {
22432243

22442244
Optional<swift::Type> ClangImporter::Implementation::importParameterType(
22452245
const clang::ParmVarDecl *param, OptionalTypeKind OptionalityOfParam,
2246-
bool allowNSUIntegerAsInt, ArrayRef<GenericTypeParamDecl *> genericParams,
2246+
bool allowNSUIntegerAsInt, bool isNSDictionarySubscriptGetter,
2247+
bool paramIsError, bool paramIsCompletionHandler,
2248+
Optional<unsigned> completionHandlerErrorParamIndex,
2249+
ArrayRef<GenericTypeParamDecl *> genericParams,
22472250
llvm::function_ref<void(Diagnostic &&)> paramAddDiag, bool &isInOut,
22482251
bool &isParamTypeImplicitlyUnwrapped) {
22492252
auto paramTy = param->getType();
@@ -2306,10 +2309,41 @@ Optional<swift::Type> ClangImporter::Implementation::importParameterType(
23062309
isInOut = true;
23072310
}
23082311

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

@@ -2378,8 +2412,12 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
23782412
bool isParamTypeImplicitlyUnwrapped = false;
23792413

23802414
auto swiftParamTyOpt = importParameterType(
2381-
param, OptionalityOfParam, importKind, allowNSUIntegerAsInt,
2382-
genericParams, paramAddDiag, isInOut, isParamTypeImplicitlyUnwrapped);
2415+
param, OptionalityOfParam, allowNSUIntegerAsInt,
2416+
/*isNSDictionarySubscriptGetter=*/false,
2417+
/*paramIsError=*/false,
2418+
/*paramIsCompletionHandler=*/false,
2419+
/*completionHandlerErrorParamIndex=*/None, genericParams, paramAddDiag,
2420+
isInOut, isParamTypeImplicitlyUnwrapped);
23832421
if (!swiftParamTyOpt) {
23842422
addImportDiagnostic(param,
23852423
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;
@@ -2945,68 +2981,22 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
29452981
allowNSUIntegerAsIntInParam = !nameContainsUnsigned(name);
29462982
}
29472983

2948-
ImportTypeKind importKind = getImportTypeKindForParam(param);
29492984
ImportDiagnosticAdder paramAddDiag(*this, clangDecl, param->getLocation());
29502985

29512986
bool isInOut = false;
29522987
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-
}
3004-
if (!swiftParamTy) {
2988+
auto swiftParamTyOpt = importParameterType(
2989+
param, optionalityOfParam, allowNSUIntegerAsIntInParam,
2990+
kind == SpecialMethodKind::NSDictionarySubscriptGetter, paramIsError,
2991+
paramIsCompletionHandler, completionHandlerErrorParamIndex,
2992+
ArrayRef<GenericTypeParamDecl *>(), paramAddDiag, isInOut, paramIsIUO);
2993+
if (!swiftParamTyOpt) {
30052994
addImportDiagnostic(param,
30062995
Diagnostic(diag::parameter_type_not_imported, param),
30072996
param->getSourceRange().getBegin());
30082997
return {Type(), false};
30092998
}
2999+
auto swiftParamTy = *swiftParamTyOpt;
30103000

30113001
swiftParamTy = mapGenericArgs(origDC, dc, swiftParamTy);
30123002

@@ -3030,6 +3020,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
30303020
decomposeCompletionHandlerType(swiftParamTy, *asyncInfo)) {
30313021
swiftResultTy = replacedSwiftResultTy;
30323022

3023+
ImportTypeKind importKind = getImportTypeKindForParam(param);
3024+
30333025
// Import the original completion handler type without adjustments.
30343026
Type origSwiftParamTy = importType(
30353027
paramTy, importKind, paramAddDiag, allowNSUIntegerAsIntInParam,

lib/ClangImporter/ImporterImpl.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,18 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13711371
/// being imported.
13721372
/// \param allowNSUIntegerAsInt If true, NSUInteger will be import as Int
13731373
/// in certain contexts. If false, it will always be import as UInt.
1374+
/// \param isNSDictionarySubscriptGetter If true, the parameter is being
1375+
/// imported as part of an NSDictionary subscript getter. If false,
1376+
/// the parameter belongs to some other kind of method/function.
1377+
/// \param paramIsError If true, the parameter being imported is an NSError
1378+
/// parameter. If false, the parameter is not an error parameter.
1379+
/// \param paramIsCompletionHandler If true, the parameter being imported is
1380+
/// a completion handler. If false, the parameter is not a completion
1381+
/// handler.
1382+
/// \param completionHandlerErrorParamIndex If it contains a value, the value
1383+
/// indicates the index of the completion handler whose error
1384+
/// parameter is used to indicate throwing. If None, the function does
1385+
/// not have such parameter.
13741386
/// \param genericParams For C++ functions, an array of the generic type
13751387
/// parameters of the function. For the rest of cases, an empty array
13761388
/// can be provided.
@@ -1386,7 +1398,10 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
13861398
/// \returns The imported parameter type on success, or None on failure.
13871399
Optional<swift::Type> importParameterType(
13881400
const clang::ParmVarDecl *param, OptionalTypeKind optionalityOfParam,
1389-
bool allowNSUIntegerAsInt, ArrayRef<GenericTypeParamDecl *> genericParams,
1401+
bool allowNSUIntegerAsInt, bool isNSDictionarySubscriptGetter,
1402+
bool paramIsError, bool paramIsCompletionHandler,
1403+
Optional<unsigned> completionHandlerErrorParamIndex,
1404+
ArrayRef<GenericTypeParamDecl *> genericParams,
13901405
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn,
13911406
bool &isInOut, bool &isParamTypeImplicitlyUnwrapped);
13921407

0 commit comments

Comments
 (0)