Skip to content

Commit c726164

Browse files
huonwmilseman
authored andcommitted
[ClangImporter] Don't resugar NSPointer for the error out parameter of throws functions.
This breaks a cycle with a function in Foundation, but isn't a complete fix: it will be similarly problematic if a function that can't have the throws conversion is added.
1 parent afca2bc commit c726164

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,8 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
11551155
ImportHint hint,
11561156
bool allowNSUIntegerAsInt,
11571157
bool canFullyBridgeTypes,
1158-
OptionalTypeKind optKind) {
1158+
OptionalTypeKind optKind,
1159+
bool resugarNSErrorPointer) {
11591160
if (importKind == ImportTypeKind::Abstract) {
11601161
return importedType;
11611162
}
@@ -1223,10 +1224,16 @@ static Type adjustTypeForConcreteImport(ClangImporter::Implementation &impl,
12231224
!= elementClass->getModuleContext()->getName())
12241225
return Type();
12251226

1226-
return impl.getNamedSwiftType(
1227-
foundationModule,
1228-
impl.SwiftContext.getSwiftName(
1229-
KnownFoundationEntity::NSErrorPointer));
1227+
1228+
if (resugarNSErrorPointer)
1229+
return impl.getNamedSwiftType(
1230+
foundationModule,
1231+
impl.SwiftContext.getSwiftName(
1232+
KnownFoundationEntity::NSErrorPointer));
1233+
1234+
// The imported type is AUMP<NSError?>, but the typealias is AUMP<NSError?>?
1235+
// so we have to manually make them match.
1236+
return OptionalType::get(importedType);
12301237
};
12311238
if (Type result = maybeImportNSErrorPointer())
12321239
return result;
@@ -1390,7 +1397,8 @@ Type ClangImporter::Implementation::importType(clang::QualType type,
13901397
ImportTypeKind importKind,
13911398
bool allowNSUIntegerAsInt,
13921399
bool canFullyBridgeTypes,
1393-
OptionalTypeKind optionality) {
1400+
OptionalTypeKind optionality,
1401+
bool resugarNSErrorPointer) {
13941402
if (type.isNull())
13951403
return Type();
13961404

@@ -1437,7 +1445,8 @@ Type ClangImporter::Implementation::importType(clang::QualType type,
14371445
importKind, importResult.Hint,
14381446
allowNSUIntegerAsInt,
14391447
canFullyBridgeTypes,
1440-
optionality);
1448+
optionality,
1449+
resugarNSErrorPointer);
14411450
}
14421451

14431452
bool ClangImporter::Implementation::shouldImportGlobalAsLet(
@@ -1981,8 +1990,9 @@ Type ClangImporter::Implementation::importMethodType(
19811990
for (size_t paramIndex = 0; paramIndex != params.size(); paramIndex++) {
19821991
auto param = params[paramIndex];
19831992
auto paramTy = param->getType();
1993+
auto paramIsError = errorInfo && paramIndex == errorInfo->ErrorParameterIndex;
19841994
if (paramTy->isVoidType()) {
1985-
assert(!errorInfo || paramIndex != errorInfo->ErrorParameterIndex);
1995+
assert(!paramIsError);
19861996
++nameIndex;
19871997
continue;
19881998
}
@@ -2023,18 +2033,27 @@ Type ClangImporter::Implementation::importMethodType(
20232033
importKind = ImportTypeKind::CFRetainedOutParameter;
20242034
else if (param->hasAttr<clang::CFReturnsNotRetainedAttr>())
20252035
importKind = ImportTypeKind::CFUnretainedOutParameter;
2026-
2036+
2037+
// If this is the throws error parameter, we don't need to convert any
2038+
// NSError** arguments to the sugared NSErrorPointer typealias form,
2039+
// because all that is done with it is retrieving the canonical
2040+
// type. Avoiding the sugar breaks a loop in Foundation caused by method
2041+
// on NSString that has an error parameter. FIXME: This is a work-around
2042+
// for the specific case when the throws conversion works, but is not
2043+
// sufficient if it fails. (The correct, overarching fix is ClangImporter
2044+
// being lazier.)
20272045
swiftParamTy = importType(paramTy, importKind,
20282046
allowNSUIntegerAsIntInParam,
20292047
/*isFullyBridgeable*/true,
2030-
optionalityOfParam);
2048+
optionalityOfParam,
2049+
/*resugarNSErrorPointer=*/!paramIsError);
20312050
}
20322051
if (!swiftParamTy)
20332052
return Type();
20342053

20352054
// If this is the error parameter, remember it, but don't build it
20362055
// into the parameter type.
2037-
if (errorInfo && paramIndex == errorInfo->ErrorParameterIndex) {
2056+
if (paramIsError) {
20382057
errorParamType = swiftParamTy->getCanonicalType();
20392058

20402059
// ...unless we're supposed to replace it with ().

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
911911
ImportTypeKind kind,
912912
bool allowNSUIntegerAsInt,
913913
bool canFullyBridgeTypes,
914-
OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional);
914+
OptionalTypeKind optional = OTK_ImplicitlyUnwrappedOptional,
915+
bool resugarNSErrorPointer = true);
915916

916917
/// \brief Import the given function type.
917918
///

test/PrintAsObjC/override.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class A_Child : Base {
3636
override func foo(_ x: Int, y: Int) -> Int { return x + y }
3737

3838

39-
// CHECK-NEXT: - (BOOL)doThingAndReturnError:(NSError * _Nullable * _Null_unspecified)error;
39+
// CHECK-NEXT: - (BOOL)doThingAndReturnError:(NSError * _Nullable * _Nullable)error;
4040
override func doThing() throws {}
4141

42-
// CHECK-NEXT: - (BOOL)doAnotherThingWithError:(NSError * _Nullable * _Null_unspecified)error;
42+
// CHECK-NEXT: - (BOOL)doAnotherThingWithError:(NSError * _Nullable * _Nullable)error;
4343
override func doAnotherThing() throws {}
4444

4545
// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;

0 commit comments

Comments
 (0)