Skip to content

Commit 6e6ca13

Browse files
committed
[Type System] Use the constraint type of an existential type in
various places that expect ProtocolType or ProtocoolCompositionType.
1 parent f018328 commit 6e6ca13

13 files changed

+70
-15
lines changed

Diff for: include/swift/AST/ProtocolConformance.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ class SelfProtocolConformance : public RootProtocolConformance {
660660
public:
661661
/// Get the protocol being conformed to.
662662
ProtocolDecl *getProtocol() const {
663-
return getType()->castTo<ProtocolType>()->getDecl();
663+
return dyn_cast<ProtocolDecl>(getType()->getAnyNominal());
664664
}
665665

666666
/// Get the declaration context in which this conformance was declared.

Diff for: include/swift/AST/Types.h

+5
Original file line numberDiff line numberDiff line change
@@ -6455,6 +6455,8 @@ inline NominalTypeDecl *TypeBase::getNominalOrBoundGenericNominal() {
64556455
inline NominalTypeDecl *CanType::getNominalOrBoundGenericNominal() const {
64566456
if (auto Ty = dyn_cast<NominalOrBoundGenericNominalType>(*this))
64576457
return Ty->getDecl();
6458+
if (auto Ty = dyn_cast<ExistentialType>(*this))
6459+
return Ty->getConstraintType()->getNominalOrBoundGenericNominal();
64586460
return nullptr;
64596461
}
64606462

@@ -6463,6 +6465,9 @@ inline NominalTypeDecl *TypeBase::getAnyNominal() {
64636465
}
64646466

64656467
inline Type TypeBase::getNominalParent() {
6468+
if (auto existential = getAs<ExistentialType>())
6469+
return existential->getConstraintType()->getNominalParent();
6470+
64666471
return castTo<AnyGenericType>()->getParent();
64676472
}
64686473

Diff for: lib/APIDigester/ModuleAnalyzerNodes.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,12 @@ static StringRef getTypeName(SDKContext &Ctx, Type Ty,
10171017
if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) {
10181018
return NAT->getDecl()->getNameStr();
10191019
}
1020+
1021+
if (auto existential = Ty->getAs<ExistentialType>()) {
1022+
return getTypeName(Ctx, existential->getConstraintType(),
1023+
IsImplicitlyUnwrappedOptional);
1024+
}
1025+
10201026
if (Ty->getAnyNominal()) {
10211027
if (IsImplicitlyUnwrappedOptional) {
10221028
assert(Ty->getOptionalObjectType());

Diff for: lib/AST/Decl.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -5164,7 +5164,10 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type,
51645164
return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant);
51655165

51665166
// Protocol compositions preserve variance.
5167-
if (auto *comp = type->getAs<ProtocolCompositionType>()) {
5167+
auto constraint = type;
5168+
if (auto existential = constraint->getAs<ExistentialType>())
5169+
constraint = existential->getConstraintType();
5170+
if (auto *comp = constraint->getAs<ProtocolCompositionType>()) {
51685171
// 'Self' may be referenced only in a superclass component.
51695172
if (const auto superclass = comp->getSuperclass()) {
51705173
return findProtocolSelfReferences(proto, superclass, position);

Diff for: lib/AST/Type.cpp

+19-5
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ NominalTypeDecl *CanType::getAnyNominal() const {
104104
}
105105

106106
GenericTypeDecl *CanType::getAnyGeneric() const {
107+
if (auto existential = dyn_cast<ExistentialType>(*this))
108+
return existential->getConstraintType()->getAnyGeneric();
107109
if (auto Ty = dyn_cast<AnyGenericType>(*this))
108110
return Ty->getDecl();
109111
return nullptr;
@@ -2643,14 +2645,17 @@ getForeignRepresentable(Type type, ForeignLanguage language,
26432645
// If type has an error let's fail early.
26442646
if (type->hasError())
26452647
return failure();
2646-
2648+
26472649
// Look through one level of optional type, but remember that we did.
26482650
bool wasOptional = false;
26492651
if (auto valueType = type->getOptionalObjectType()) {
26502652
type = valueType;
26512653
wasOptional = true;
26522654
}
26532655

2656+
if (auto existential = type->getAs<ExistentialType>())
2657+
type = existential->getConstraintType();
2658+
26542659
// Objective-C object types, including metatypes.
26552660
if (language == ForeignLanguage::ObjectiveC) {
26562661
auto representable = getObjCObjectRepresentable(type, dc);
@@ -3242,9 +3247,14 @@ Type ArchetypeType::getExistentialType() const {
32423247
for (auto proto : getConformsTo()) {
32433248
constraintTypes.push_back(proto->getDeclaredInterfaceType());
32443249
}
3245-
return ProtocolCompositionType::get(
3246-
const_cast<ArchetypeType*>(this)->getASTContext(), constraintTypes,
3247-
requiresClass());
3250+
auto &ctx = const_cast<ArchetypeType*>(this)->getASTContext();
3251+
auto constraint = ProtocolCompositionType::get(
3252+
ctx, constraintTypes, requiresClass());
3253+
3254+
if (ctx.LangOpts.EnableExplicitExistentialTypes)
3255+
return ExistentialType::get(constraint);
3256+
3257+
return constraint;
32483258
}
32493259

32503260
PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx,
@@ -5555,6 +5565,10 @@ bool Type::isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic) const {
55555565
if (!Ty)
55565566
return false;
55575567

5568+
if (auto existential = dyn_cast<ExistentialType>(Ty.getPointer()))
5569+
return existential->getConstraintType()
5570+
.isPrivateStdlibType(treatNonBuiltinProtocolsAsPublic);
5571+
55585572
// A 'public' typealias can have an 'internal' type.
55595573
if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) {
55605574
auto *AliasDecl = NAT->getDecl();
@@ -5739,7 +5753,7 @@ SILBoxType::SILBoxType(ASTContext &C,
57395753
Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
57405754
assert(isAnyExistentialType());
57415755
if (auto metaty = getAs<ExistentialMetatypeType>()) {
5742-
opened = OpenedArchetypeType::get(metaty->getInstanceType());
5756+
opened = OpenedArchetypeType::get(metaty->getExistentialInstanceType());
57435757
if (metaty->hasRepresentation())
57445758
return MetatypeType::get(opened, metaty->getRepresentation());
57455759
else

Diff for: lib/IRGen/DebugTypeInfo.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ TypeDecl *DebugTypeInfo::getDecl() const {
158158
return UBG->getDecl();
159159
if (auto *BG = dyn_cast<BoundGenericType>(Type))
160160
return BG->getDecl();
161+
if (auto *E = dyn_cast<ExistentialType>(Type))
162+
return E->getConstraintType()->getAnyNominal();
161163
return nullptr;
162164
}
163165

Diff for: lib/IRGen/IRGenMangler.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ std::string IRGenMangler::mangleTypeForLLVMTypeName(CanType Ty) {
216216
// To make LLVM IR more readable we always add a 'T' prefix so that type names
217217
// don't start with a digit and don't need to be quoted.
218218
Buffer << 'T';
219+
if (auto existential = Ty->getAs<ExistentialType>())
220+
Ty = existential->getConstraintType()->getCanonicalType();
219221
if (auto P = dyn_cast<ProtocolType>(Ty)) {
220222
appendProtocolName(P->getDecl(), /*allowStandardSubstitution=*/false);
221223
appendOperator("P");

Diff for: lib/SIL/Utils/DynamicCasts.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,7 @@ swift::classifyDynamicCast(ModuleDecl *M,
468468
: DynamicCastFeasibility::WillFail;
469469
}
470470

471-
if (targetMetatype.isAnyExistentialType() &&
472-
(isa<ProtocolType>(target) || isa<ProtocolCompositionType>(target))) {
471+
if (targetMetatype.isAnyExistentialType() && target->isExistentialType()) {
473472
auto Feasibility =
474473
classifyDynamicCastToProtocol(M, source, target, isWholeModuleOpts);
475474
// Cast from existential metatype to existential metatype may still

Diff for: lib/SILGen/SILGenConvert.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,11 @@ ManagedValue SILGenFunction::emitExistentialMetatypeToObject(SILLocation loc,
913913
ManagedValue SILGenFunction::emitProtocolMetatypeToObject(SILLocation loc,
914914
CanType inputTy,
915915
SILType resultTy) {
916-
ProtocolDecl *protocol = inputTy->castTo<MetatypeType>()
917-
->getInstanceType()->castTo<ProtocolType>()->getDecl();
916+
auto protocolType = inputTy->castTo<MetatypeType>()->getInstanceType();
917+
if (auto existential = protocolType->getAs<ExistentialType>())
918+
protocolType = existential->getConstraintType();
919+
920+
ProtocolDecl *protocol = protocolType->castTo<ProtocolType>()->getDecl();
918921

919922
SILValue value = B.createObjCProtocol(loc, protocol, resultTy);
920923

Diff for: lib/SILGen/SILGenType.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,10 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM,
842842
ProtocolConformanceRef(conformance));
843843

844844
// Open the protocol type.
845-
auto openedType = OpenedArchetypeType::get(protocolType);
845+
Type existential = protocolType;
846+
if (SGM.getASTContext().LangOpts.EnableExplicitExistentialTypes)
847+
existential = ExistentialType::get(protocolType);
848+
auto openedType = OpenedArchetypeType::get(existential);
846849

847850
// Form the substitutions for calling the witness.
848851
auto witnessSubs = SubstitutionMap::getProtocolSubstitutions(protocol,

Diff for: lib/Sema/TypeCheckAccess.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,12 @@ class AccessControlChecker : public AccessControlCheckerBase,
783783
Type());
784784
}
785785

786-
auto declKindForType = [](Type type) {
786+
auto declKindForType = [](Type type) -> DescriptiveDeclKind {
787+
// If this is an existential type, use the decl kind of
788+
// its constraint type.
789+
if (auto existential = type->getAs<ExistentialType>())
790+
type = existential->getConstraintType();
791+
787792
if (isa<TypeAliasType>(type.getPointer()))
788793
return DescriptiveDeclKind::TypeAlias;
789794
else if (auto nominal = type->getAnyNominal())

Diff for: lib/Sema/TypeCheckDecl.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,13 @@ bool swift::isMemberOperator(FuncDecl *decl, Type type) {
18991899
}
19001900

19011901
if (isProtocol) {
1902+
// FIXME: Source compatibility hack for Swift 5. The compiler
1903+
// accepts member operators on protocols with existential
1904+
// type arguments. We should consider banning this in Swift 6.
1905+
if (auto existential = paramType->getAs<ExistentialType>()) {
1906+
return selfNominal == existential->getConstraintType()->getAnyNominal();
1907+
}
1908+
19021909
// For a protocol, is it the 'Self' type parameter?
19031910
if (auto genericParam = paramType->getAs<GenericTypeParamType>())
19041911
if (genericParam->isEqual(DC->getSelfInterfaceType()))

Diff for: lib/Sema/TypeCheckProtocol.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -5273,8 +5273,11 @@ void swift::diagnoseConformanceFailure(Type T,
52735273
TypeChecker::containsProtocol(T, Proto, DC->getParentModule())) {
52745274

52755275
if (!T->isObjCExistentialType()) {
5276+
Type constraintType = T;
5277+
if (auto existential = T->getAs<ExistentialType>())
5278+
constraintType = existential->getConstraintType();
52765279
diags.diagnose(ComplainLoc, diag::type_cannot_conform, true,
5277-
T, T->isEqual(Proto->getDeclaredInterfaceType()),
5280+
T, constraintType->isEqual(Proto->getDeclaredInterfaceType()),
52785281
Proto->getDeclaredInterfaceType());
52795282
diags.diagnose(ComplainLoc,
52805283
diag::only_concrete_types_conform_to_protocols);
@@ -5407,7 +5410,10 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M,
54075410
if (T->isExistentialType()) {
54085411
// Handle the special case of the Error protocol, which self-conforms
54095412
// *and* has a witness table.
5410-
if (T->isEqual(Proto->getDeclaredInterfaceType()) &&
5413+
auto constraint = T;
5414+
if (auto existential = T->getAs<ExistentialType>())
5415+
constraint = existential->getConstraintType();
5416+
if (constraint->isEqual(Proto->getDeclaredInterfaceType()) &&
54115417
Proto->requiresSelfConformanceWitnessTable()) {
54125418
auto &ctx = M->getASTContext();
54135419
return ProtocolConformanceRef(ctx.getSelfConformance(Proto));

0 commit comments

Comments
 (0)