Skip to content

Commit 53305f1

Browse files
authored
Merge pull request #8847 from slavapestov/subclass-existentials-clang-importer
ClangImporter: Support for subclass existentials
2 parents 3715d4c + 57b2c05 commit 53305f1

File tree

13 files changed

+302
-96
lines changed

13 files changed

+302
-96
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ enum LayoutRequirementKind : uint8_t {
261261
Trivial = 3,
262262
RefCountedObject = 4,
263263
NativeRefCountedObject = 5,
264+
Class = 6,
265+
NativeClass = 7
264266
};
265267
using LayoutRequirementKindField = BCFixed<3>;
266268

lib/ClangImporter/ImportType.cpp

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,8 @@ namespace {
848848

849849
ImportResult
850850
VisitObjCObjectPointerType(const clang::ObjCObjectPointerType *type) {
851+
Type importedType = Impl.SwiftContext.getAnyObjectType();
852+
851853
// If this object pointer refers to an Objective-C class (possibly
852854
// qualified),
853855
if (auto objcClass = type->getInterfaceDecl()) {
@@ -856,7 +858,6 @@ namespace {
856858
if (!imported)
857859
return nullptr;
858860

859-
Type importedType;
860861
// If the objc type has any generic args, convert them and bind them to
861862
// the imported class type.
862863
if (imported->getGenericParams()) {
@@ -873,21 +874,30 @@ namespace {
873874
return nullptr;
874875
}
875876
importedTypeArg = subresult.AbstractType;
876-
} else if (typeParam->getSuperclass()) {
877-
// FIXME: Can we have both a superclass and protocols?
877+
} else if (typeParam->getSuperclass() &&
878+
(Impl.SwiftContext.isSwiftVersion3() ||
879+
typeParam->getConformingProtocols().empty())) {
880+
// In Swift 3 mode, discard the protocol bounds if there is
881+
// a superclass bound.
878882
importedTypeArg = typeParam->getSuperclass();
879883
} else {
880-
auto protocols = typeParam->getConformingProtocols();
881-
assert(!protocols.empty() &&
882-
"objc imported type param should have either superclass or "
883-
"protocol requirement");
884-
SmallVector<Type, 4> protocolTypes;
885-
for (auto protocolDecl : protocols) {
886-
protocolTypes.push_back(protocolDecl->getDeclaredType());
884+
SmallVector<Type, 4> memberTypes;
885+
886+
if (Impl.SwiftContext.LangOpts.EnableExperimentalSubclassExistentials) {
887+
if (auto superclassType = typeParam->getSuperclass())
888+
memberTypes.push_back(superclassType);
887889
}
890+
891+
for (auto protocolDecl : typeParam->getConformingProtocols())
892+
memberTypes.push_back(protocolDecl->getDeclaredType());
893+
894+
bool hasExplicitAnyObject = false;
895+
if (memberTypes.empty())
896+
hasExplicitAnyObject = true;
897+
888898
importedTypeArg = ProtocolCompositionType::get(
889-
Impl.SwiftContext, protocolTypes,
890-
/*hasExplicitAnyObject=*/false);
899+
Impl.SwiftContext, memberTypes,
900+
hasExplicitAnyObject);
891901
}
892902
importedTypeArgs.push_back(importedTypeArg);
893903
}
@@ -1014,47 +1024,50 @@ namespace {
10141024
return { importedType,
10151025
ImportHint(ImportHint::ObjCBridged, bridgedType) };
10161026
}
1017-
1018-
return { importedType, ImportHint::ObjCPointer };
10191027
}
10201028

1021-
// If this is id<P> or Class<P>, turn this into a protocol type.
1022-
if (type->isObjCQualifiedIdType() || type->isObjCQualifiedClassType()) {
1023-
SmallVector<Type, 4> protocols;
1029+
// Swift 3 compatibility -- don't import subclass existentials
1030+
if (!type->qual_empty() &&
1031+
(importedType->isAnyObject() ||
1032+
(!Impl.SwiftContext.isSwiftVersion3() &&
1033+
Impl.SwiftContext.LangOpts.EnableExperimentalSubclassExistentials))) {
1034+
1035+
SmallVector<Type, 4> members;
1036+
if (!importedType->isAnyObject())
1037+
members.push_back(importedType);
1038+
10241039
for (auto cp = type->qual_begin(), cpEnd = type->qual_end();
10251040
cp != cpEnd; ++cp) {
10261041
auto proto = cast_or_null<ProtocolDecl>(
1027-
Impl.importDecl(*cp, Impl.CurrentVersion));
1042+
Impl.importDecl(*cp, Impl.CurrentVersion));
10281043
if (!proto)
10291044
return Type();
10301045

1031-
protocols.push_back(proto->getDeclaredType());
1046+
members.push_back(proto->getDeclaredType());
10321047
}
10331048

1034-
// FIXME: Handle isObjCQualifiedClassType() case by adding a superclass
1035-
// constraint here
1036-
Type result = ProtocolCompositionType::get(Impl.SwiftContext,
1037-
protocols,
1038-
/*HasExplicitAnyObject=*/false);
1039-
if (type->isObjCQualifiedClassType())
1040-
result = ExistentialMetatypeType::get(result);
1049+
importedType = ProtocolCompositionType::get(Impl.SwiftContext,
1050+
members,
1051+
/*HasExplicitAnyObject=*/false);
1052+
}
10411053

1042-
return { result, ImportHint::ObjCPointer };
1054+
// Class or Class<P> maps to an existential metatype.
1055+
if (type->isObjCClassType() ||
1056+
type->isObjCQualifiedClassType()) {
1057+
importedType = ExistentialMetatypeType::get(importedType);
1058+
return { importedType, ImportHint::ObjCPointer };
10431059
}
1044-
1060+
10451061
// Beyond here, we're using AnyObject.
10461062

10471063
// id maps to Any in bridgeable contexts, AnyObject otherwise.
10481064
if (type->isObjCIdType()) {
1049-
return {Impl.SwiftContext.getAnyObjectType(),
1050-
ImportHint(ImportHint::ObjCBridged,
1051-
Impl.SwiftContext.TheAnyType)};
1065+
return { Impl.SwiftContext.getAnyObjectType(),
1066+
ImportHint(ImportHint::ObjCBridged,
1067+
Impl.SwiftContext.TheAnyType)};
10521068
}
10531069

1054-
// Class maps to AnyObject.Type.
1055-
assert(type->isObjCClassType());
1056-
return { ExistentialMetatypeType::get(Impl.SwiftContext.getAnyObjectType()),
1057-
ImportHint::ObjCPointer };
1070+
return { importedType, ImportHint::ObjCPointer };
10581071
}
10591072
};
10601073
} // end anonymous namespace

lib/IRGen/GenExistential.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,8 @@ class ClassExistentialTypeInfo final
10831083
std::move(spareBits), align),
10841084
Refcounting(refcounting) {
10851085
assert(refcounting == ReferenceCounting::Native ||
1086-
refcounting == ReferenceCounting::Unknown);
1086+
refcounting == ReferenceCounting::Unknown ||
1087+
refcounting == ReferenceCounting::ObjC);
10871088
}
10881089

10891090
public:

lib/Serialization/Deserialization.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,31 +1030,31 @@ void ModuleFile::readGenericRequirements(
10301030
error();
10311031
break;
10321032
}
1033-
case LayoutRequirementKind::NativeRefCountedObject: {
1033+
case LayoutRequirementKind::NativeRefCountedObject:
10341034
kind = LayoutConstraintKind::NativeRefCountedObject;
10351035
break;
1036-
}
1037-
case LayoutRequirementKind::RefCountedObject: {
1036+
case LayoutRequirementKind::RefCountedObject:
10381037
kind = LayoutConstraintKind::RefCountedObject;
10391038
break;
1040-
}
1041-
case LayoutRequirementKind::Trivial: {
1039+
case LayoutRequirementKind::Trivial:
10421040
kind = LayoutConstraintKind::Trivial;
10431041
break;
1044-
}
1045-
case LayoutRequirementKind::TrivialOfExactSize: {
1042+
case LayoutRequirementKind::TrivialOfExactSize:
10461043
kind = LayoutConstraintKind::TrivialOfExactSize;
10471044
break;
1048-
}
1049-
case LayoutRequirementKind::TrivialOfAtMostSize: {
1045+
case LayoutRequirementKind::TrivialOfAtMostSize:
10501046
kind = LayoutConstraintKind::TrivialOfAtMostSize;
10511047
break;
1052-
}
1053-
case LayoutRequirementKind::UnknownLayout: {
1048+
case LayoutRequirementKind::Class:
1049+
kind = LayoutConstraintKind::Class;
1050+
break;
1051+
case LayoutRequirementKind::NativeClass:
1052+
kind = LayoutConstraintKind::NativeClass;
1053+
break;
1054+
case LayoutRequirementKind::UnknownLayout:
10541055
kind = LayoutConstraintKind::UnknownLayout;
10551056
break;
10561057
}
1057-
}
10581058

10591059
ASTContext &ctx = getContext();
10601060
if (kind != LayoutConstraintKind::TrivialOfAtMostSize &&

lib/Serialization/Serialization.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,8 +1122,35 @@ void Serializer::writeGenericRequirements(ArrayRef<Requirement> requirements,
11221122
size = layout->getTrivialSizeInBits();
11231123
alignment = layout->getAlignment();
11241124
}
1125+
LayoutRequirementKind rawKind = LayoutRequirementKind::UnknownLayout;
1126+
switch (layout->getKind()) {
1127+
case LayoutConstraintKind::NativeRefCountedObject:
1128+
rawKind = LayoutRequirementKind::NativeRefCountedObject;
1129+
break;
1130+
case LayoutConstraintKind::RefCountedObject:
1131+
rawKind = LayoutRequirementKind::RefCountedObject;
1132+
break;
1133+
case LayoutConstraintKind::Trivial:
1134+
rawKind = LayoutRequirementKind::Trivial;
1135+
break;
1136+
case LayoutConstraintKind::TrivialOfExactSize:
1137+
rawKind = LayoutRequirementKind::TrivialOfExactSize;
1138+
break;
1139+
case LayoutConstraintKind::TrivialOfAtMostSize:
1140+
rawKind = LayoutRequirementKind::TrivialOfAtMostSize;
1141+
break;
1142+
case LayoutConstraintKind::Class:
1143+
rawKind = LayoutRequirementKind::Class;
1144+
break;
1145+
case LayoutConstraintKind::NativeClass:
1146+
rawKind = LayoutRequirementKind::NativeClass;
1147+
break;
1148+
case LayoutConstraintKind::UnknownLayout:
1149+
rawKind = LayoutRequirementKind::UnknownLayout;
1150+
break;
1151+
}
11251152
LayoutRequirementLayout::emitRecord(
1126-
Out, ScratchRecord, layoutReqAbbrCode, (unsigned)layout->getKind(),
1153+
Out, ScratchRecord, layoutReqAbbrCode, rawKind,
11271154
addTypeRef(req.getFirstType()), size, alignment);
11281155
}
11291156
}

0 commit comments

Comments
 (0)