Skip to content

Commit fd11d2e

Browse files
committed
[ClangImporter] Decide whether to import Objective-C pointer types as
protocol types or existential types based on context. When an id<P> type is the underlying type of a typedef or a generic constraint, it should be imported as a protocol or composition. Otherwise, it should be imported as an existential type. This is similar to how type resolution resolves existential types using TypeResolverContext.
1 parent f886b38 commit fd11d2e

File tree

3 files changed

+35
-17
lines changed

3 files changed

+35
-17
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,16 +2796,6 @@ namespace {
27962796
SourceLoc(), Name,
27972797
Loc,
27982798
/*genericparams*/nullptr, DC);
2799-
2800-
// Unwrap an explicit ExistentialType around the underlying type so that
2801-
// the typealias can be used in a generic constraint context.
2802-
//
2803-
// FIXME: We might want to push this down further into importType(), and
2804-
// once ExistentialType becomes mandatory in the future we want to wrap
2805-
// references to imported typealiases in Sema's resolveType() as well.
2806-
if (auto *existentialType = SwiftType->getAs<ExistentialType>())
2807-
SwiftType = existentialType->getConstraintType();
2808-
28092799
Result->setUnderlyingType(SwiftType);
28102800

28112801
// Make Objective-C's 'id' unavailable.

lib/ClangImporter/ImportType.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,7 @@ namespace {
10501050
if (memberTypes.empty())
10511051
hasExplicitAnyObject = true;
10521052

1053+
// Generic arguments are always imported as existential types.
10531054
Type importedTypeArg = ExistentialType::get(
10541055
ProtocolCompositionType::get(
10551056
Impl.SwiftContext, memberTypes,
@@ -1182,9 +1183,6 @@ namespace {
11821183
}
11831184
}
11841185

1185-
if (bridgedType->isConstraintType())
1186-
bridgedType = ExistentialType::get(bridgedType);
1187-
11881186
return { importedType,
11891187
ImportHint(ImportHint::ObjCBridged, bridgedType) };
11901188
}
@@ -1205,9 +1203,9 @@ namespace {
12051203
members.push_back(proto->getDeclaredInterfaceType());
12061204
}
12071205

1208-
importedType = ExistentialType::get(
1206+
importedType =
12091207
ProtocolCompositionType::get(Impl.SwiftContext, members,
1210-
/*HasExplicitAnyObject=*/false));
1208+
/*HasExplicitAnyObject=*/false);
12111209
}
12121210

12131211
// Class or Class<P> maps to an existential metatype.
@@ -1285,6 +1283,32 @@ static bool isCFAudited(ImportTypeKind importKind) {
12851283
llvm_unreachable("Invalid ImportTypeKind.");
12861284
}
12871285

1286+
/// True if the type can be an existential type in this context.
1287+
static bool isExistentialContext(ImportTypeKind importKind) {
1288+
switch (importKind) {
1289+
case ImportTypeKind::Abstract:
1290+
case ImportTypeKind::Typedef:
1291+
return false;
1292+
case ImportTypeKind::Value:
1293+
case ImportTypeKind::ObjCCollectionElement:
1294+
case ImportTypeKind::Variable:
1295+
case ImportTypeKind::Result:
1296+
case ImportTypeKind::Enum:
1297+
case ImportTypeKind::RecordField:
1298+
case ImportTypeKind::AuditedVariable:
1299+
case ImportTypeKind::AuditedResult:
1300+
case ImportTypeKind::Parameter:
1301+
case ImportTypeKind::CompletionHandlerResultParameter:
1302+
case ImportTypeKind::CFRetainedOutParameter:
1303+
case ImportTypeKind::CFUnretainedOutParameter:
1304+
case ImportTypeKind::Property:
1305+
case ImportTypeKind::PropertyWithReferenceSemantics:
1306+
return true;
1307+
}
1308+
1309+
llvm_unreachable("Invalid ImportTypeKind.");
1310+
}
1311+
12881312
/// Turn T into Unmanaged<T>.
12891313
static Type getUnmanagedType(ClangImporter::Implementation &impl,
12901314
Type payloadType) {
@@ -1550,6 +1574,11 @@ static ImportedType adjustTypeForConcreteImport(
15501574

15511575
assert(importedType);
15521576

1577+
if (importedType->isConstraintType() &&
1578+
isExistentialContext(importKind)) {
1579+
importedType = ExistentialType::get(importedType);
1580+
}
1581+
15531582
if (importKind == ImportTypeKind::RecordField &&
15541583
importedType->isAnyClassReferenceType() &&
15551584
!importedType->isForeignReferenceType()) {

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,8 +1835,7 @@ class DeclAndTypePrinter::Implementation
18351835

18361836
void visitExistentialType(ExistentialType *ET,
18371837
Optional<OptionalTypeKind> optionalKind) {
1838-
visitExistentialType(ET, optionalKind,
1839-
/*isMetatype=*/ET->getConstraintType()->is<AnyMetatypeType>());
1838+
visitPart(ET->getConstraintType(), optionalKind);
18401839
}
18411840

18421841
void visitExistentialMetatypeType(ExistentialMetatypeType *MT,

0 commit comments

Comments
 (0)