Skip to content

Commit a505698

Browse files
authored
Merge pull request #59657 from hborla/5.7-existential-any-anyobject
[5.7][Sema] Use `ExistentialType` for `Any` and `AnyObject`.
2 parents 8305829 + 7492448 commit a505698

26 files changed

+151
-99
lines changed

include/swift/AST/ASTContext.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ class ASTContext final {
537537
/// Retrieve the declaration of Swift.Error.
538538
ProtocolDecl *getErrorDecl() const;
539539
CanType getErrorExistentialType() const;
540-
540+
541541
#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
542542
/** Retrieve the declaration of Swift.NAME. */ \
543543
DECL_CLASS *get##NAME##Decl() const; \
@@ -561,7 +561,13 @@ class ASTContext final {
561561
/// Retrieve the declaration of the "pointee" property of a pointer type.
562562
VarDecl *getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const;
563563

564-
/// Retrieve the type Swift.AnyObject.
564+
/// Retrieve the type Swift.Any as an existential type.
565+
CanType getAnyExistentialType() const;
566+
567+
/// Retrieve the type Swift.AnyObject as a constraint.
568+
CanType getAnyObjectConstraint() const;
569+
570+
/// Retrieve the type Swift.AnyObject as an existential type.
565571
CanType getAnyObjectType() const;
566572

567573
#define KNOWN_SDK_TYPE_DECL(MODULE, NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \

include/swift/AST/ASTSynthesis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ enum SingletonTypeSynthesizer {
5454
inline Type synthesizeType(SynthesisContext &SC,
5555
SingletonTypeSynthesizer kind) {
5656
switch (kind) {
57-
case _any: return SC.Context.TheAnyType;
57+
case _any: return SC.Context.getAnyExistentialType();
5858
case _bridgeObject: return SC.Context.TheBridgeObjectType;
5959
case _error: return SC.Context.getErrorExistentialType();
6060
case _executor: return SC.Context.TheExecutorType;

include/swift/AST/Types.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,17 +5398,35 @@ struct ExistentialTypeGeneralization {
53985398
class ExistentialType final : public TypeBase {
53995399
Type ConstraintType;
54005400

5401+
/// Whether to print this existential type with the 'any' keyword,
5402+
/// e.g. in diagnostics.
5403+
///
5404+
/// Any and AnyObject need not use 'any', and they are printed
5405+
/// in diagnostics without 'any' unless wrapped in MetatypeType.
5406+
/// This field should only be used by TypePrinter.
5407+
bool PrintWithAny;
5408+
54015409
ExistentialType(Type constraintType,
5410+
bool printWithAny,
54025411
const ASTContext *canonicalContext,
54035412
RecursiveTypeProperties properties)
54045413
: TypeBase(TypeKind::Existential, canonicalContext, properties),
5405-
ConstraintType(constraintType) {}
5414+
ConstraintType(constraintType), PrintWithAny(printWithAny) {}
54065415

54075416
public:
5408-
static Type get(Type constraint, bool forceExistential = false);
5417+
static Type get(Type constraint);
54095418

54105419
Type getConstraintType() const { return ConstraintType; }
54115420

5421+
bool shouldPrintWithAny() const { return PrintWithAny; }
5422+
5423+
void forcePrintWithAny(llvm::function_ref<void(Type)> print) {
5424+
bool oldValue = PrintWithAny;
5425+
PrintWithAny = true;
5426+
print(this);
5427+
PrintWithAny = oldValue;
5428+
}
5429+
54125430
bool requiresClass() const {
54135431
if (auto protocol = ConstraintType->getAs<ProtocolType>())
54145432
return protocol->requiresClass();

lib/AST/ASTContext.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,11 @@ ASTContext::getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const {
956956
llvm_unreachable("bad pointer kind");
957957
}
958958

959-
CanType ASTContext::getAnyObjectType() const {
959+
CanType ASTContext::getAnyExistentialType() const {
960+
return ExistentialType::get(TheAnyType)->getCanonicalType();
961+
}
962+
963+
CanType ASTContext::getAnyObjectConstraint() const {
960964
if (getImpl().AnyObjectType) {
961965
return getImpl().AnyObjectType;
962966
}
@@ -967,6 +971,11 @@ CanType ASTContext::getAnyObjectType() const {
967971
return getImpl().AnyObjectType;
968972
}
969973

974+
CanType ASTContext::getAnyObjectType() const {
975+
return ExistentialType::get(getAnyObjectConstraint())
976+
->getCanonicalType();
977+
}
978+
970979
#define KNOWN_SDK_TYPE_DECL(MODULE, NAME, DECLTYPE, GENERIC_ARGS) \
971980
DECLTYPE *ASTContext::get##NAME##Decl() const { \
972981
if (!getImpl().NAME##Decl) { \
@@ -4242,20 +4251,18 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, Type Parent,
42424251
RecursiveTypeProperties properties)
42434252
: NominalType(TypeKind::Protocol, &Ctx, TheDecl, Parent, properties) { }
42444253

4245-
Type ExistentialType::get(Type constraint, bool forceExistential) {
4254+
Type ExistentialType::get(Type constraint) {
42464255
auto &C = constraint->getASTContext();
4247-
if (!forceExistential) {
4248-
// FIXME: Any and AnyObject don't yet use ExistentialType.
4249-
if (constraint->isAny() || constraint->isAnyObject())
4250-
return constraint;
4251-
4252-
// ExistentialMetatypeType is already an existential type.
4253-
if (constraint->is<ExistentialMetatypeType>())
4254-
return constraint;
4255-
}
4256+
// ExistentialMetatypeType is already an existential type.
4257+
if (constraint->is<ExistentialMetatypeType>())
4258+
return constraint;
42564259

42574260
assert(constraint->isConstraintType());
42584261

4262+
bool printWithAny = true;
4263+
if (constraint->isEqual(C.TheAnyType) || constraint->isAnyObject())
4264+
printWithAny = false;
4265+
42594266
auto properties = constraint->getRecursiveProperties();
42604267
if (constraint->is<ParameterizedProtocolType>())
42614268
properties |= RecursiveTypeProperties::HasParameterizedExistential;
@@ -4266,7 +4273,7 @@ Type ExistentialType::get(Type constraint, bool forceExistential) {
42664273
return entry;
42674274

42684275
const ASTContext *canonicalContext = constraint->isCanonical() ? &C : nullptr;
4269-
return entry = new (C, arena) ExistentialType(constraint,
4276+
return entry = new (C, arena) ExistentialType(constraint, printWithAny,
42704277
canonicalContext,
42714278
properties);
42724279
}

lib/AST/ASTPrinter.cpp

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5145,7 +5145,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
51455145
llvm_unreachable("bad opaque-return-type printing mode");
51465146
}
51475147
} else if (auto existential = dyn_cast<ExistentialType>(T.getPointer())) {
5148-
if (!Options.PrintExplicitAny)
5148+
if (!Options.PrintExplicitAny || !existential->shouldPrintWithAny())
51495149
return isSimpleUnderPrintOptions(existential->getConstraintType());
51505150
} else if (auto existential = dyn_cast<ExistentialMetatypeType>(T.getPointer())) {
51515151
if (!Options.PrintExplicitAny)
@@ -5581,31 +5581,30 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55815581
}
55825582

55835583
Type instanceType = T->getInstanceType();
5584-
if (Options.PrintExplicitAny) {
5585-
if (T->is<ExistentialMetatypeType>()) {
5586-
Printer << "any ";
5587-
5588-
// FIXME: We need to replace nested existential metatypes so that
5589-
// we don't print duplicate 'any'. This will be unnecessary once
5590-
// ExistentialMetatypeType is split into ExistentialType(MetatypeType).
5591-
instanceType = Type(instanceType).transform([](Type type) -> Type {
5592-
if (auto existential = type->getAs<ExistentialMetatypeType>())
5593-
return MetatypeType::get(existential->getInstanceType());
5594-
5595-
return type;
5596-
});
5597-
} else if (instanceType->isAny() || instanceType->isAnyObject()) {
5598-
// FIXME: 'any' is needed to distinguish between '(any Any).Type'
5599-
// and 'any Any.Type'. However, this combined with the above hack
5600-
// to replace nested existential metatypes with metatypes causes
5601-
// a bug in printing nested existential metatypes for Any and AnyObject,
5602-
// e.g. 'any (any Any).Type.Type'. This will be fixed by using
5603-
// ExistentialType for Any and AnyObject.
5604-
instanceType = ExistentialType::get(instanceType, /*forceExistential=*/true);
5605-
}
5606-
}
5584+
if (Options.PrintExplicitAny && T->is<ExistentialMetatypeType>()) {
5585+
Printer << "any ";
5586+
5587+
// FIXME: We need to replace nested existential metatypes so that
5588+
// we don't print duplicate 'any'. This will be unnecessary once
5589+
// ExistentialMetatypeType is split into ExistentialType(MetatypeType).
5590+
printWithParensIfNotSimple(instanceType.transform([](Type type) -> Type {
5591+
if (auto existential = type->getAs<ExistentialMetatypeType>())
5592+
return MetatypeType::get(existential->getInstanceType());
56075593

5608-
printWithParensIfNotSimple(instanceType);
5594+
return type;
5595+
}));
5596+
} else if (T->is<MetatypeType>() && instanceType->is<ExistentialType>()) {
5597+
// The 'any' keyword is needed to distinguish between existential
5598+
// metatypes and singleton metatypes. However, 'any' usually isn't
5599+
// printed for Any and AnyObject, because it's unnecessary to write
5600+
// 'any' with these specific constraints. Force printing with 'any'
5601+
// for the existential instance type in this case.
5602+
instanceType->getAs<ExistentialType>()->forcePrintWithAny([&](Type ty) {
5603+
printWithParensIfNotSimple(ty);
5604+
});
5605+
} else {
5606+
printWithParensIfNotSimple(instanceType);
5607+
}
56095608

56105609
// We spell normal metatypes of existential types as .Protocol.
56115610
if (isa<MetatypeType>(T) &&
@@ -6217,15 +6216,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
62176216
}
62186217

62196218
void visitExistentialType(ExistentialType *T) {
6220-
if (Options.PrintExplicitAny)
6219+
if (Options.PrintExplicitAny && T->shouldPrintWithAny())
62216220
Printer << "any ";
62226221

62236222
// FIXME: The desugared type is used here only to support
62246223
// existential types with protocol typealiases in Swift
62256224
// interfaces. Verifying that the underlying type of a
62266225
// protocol typealias is a constriant type is fundamentally
62276226
// circular, so the desugared type should be written in source.
6228-
if (Options.DesugarExistentialConstraint) {
6227+
if (Options.DesugarExistentialConstraint && !T->isAnyObject()) {
62296228
visit(T->getConstraintType()->getDesugaredType());
62306229
} else {
62316230
visit(T->getConstraintType());

lib/AST/Builtins.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ namespace {
682682
if (wantsAdditionalAnyObjectRequirement) {
683683
Requirement req(RequirementKind::Conformance,
684684
TheGenericParamList->getParams()[0]->getInterfaceType(),
685-
ctx.getAnyObjectType());
685+
ctx.getAnyObjectConstraint());
686686
addedRequirements.push_back(req);
687687
}
688688
for (auto gp : TheGenericParamList->getParams()) {

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2847,7 +2847,7 @@ static Type mapSignatureFunctionType(ASTContext &ctx, Type type,
28472847
// Functions and subscripts cannot overload differing only in opaque return
28482848
// types. Replace the opaque type with `Any`.
28492849
if (type->is<OpaqueTypeArchetypeType>()) {
2850-
type = ProtocolCompositionType::get(ctx, {}, /*hasAnyObject*/ false);
2850+
type = ctx.getAnyExistentialType();
28512851
}
28522852

28532853
return mapSignatureParamType(ctx, type);

lib/AST/Type.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ bool TypeBase::isStructurallyUninhabited() {
158158
}
159159

160160
bool TypeBase::isAny() {
161-
return isEqual(getASTContext().TheAnyType);
161+
Type constraint = this;
162+
if (auto existential = constraint->getAs<ExistentialType>())
163+
constraint = existential->getConstraintType();
164+
return constraint->isEqual(getASTContext().TheAnyType);
162165
}
163166

164167
bool TypeBase::isPlaceholder() {

lib/AST/TypeJoinMeet.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> {
4545
// For convenience, TheAnyType from ASTContext;
4646
CanType TheAnyType;
4747

48+
CanType getAnyExistentialType() {
49+
return ExistentialType::get(TheAnyType)->getCanonicalType();
50+
}
51+
4852
TypeJoin(CanType First) : First(First), Unimplemented(CanType()) {
4953
assert(First && "Unexpected null type!");
5054
TheAnyType = First->getASTContext().TheAnyType;
@@ -112,10 +116,10 @@ struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> {
112116

113117
// Likewise, rather than making every visitor deal with Any,
114118
// always dispatch to the protocol composition side of the join.
115-
if (first->is<ProtocolCompositionType>())
119+
if (first->is<ProtocolCompositionType>() || first->is<ExistentialType>())
116120
return TypeJoin(second).visit(first);
117121

118-
if (second->is<ProtocolCompositionType>())
122+
if (second->is<ProtocolCompositionType>() || second->is<ExistentialType>())
119123
return TypeJoin(first).visit(second);
120124

121125
// Otherwise the first type might be an optional (or not), so
@@ -166,7 +170,7 @@ CanType TypeJoin::visitErrorType(CanType second) {
166170
CanType TypeJoin::visitTupleType(CanType second) {
167171
assert(First != second);
168172

169-
return TheAnyType;
173+
return getAnyExistentialType();
170174
}
171175

172176
CanType TypeJoin::visitEnumType(CanType second) {
@@ -184,7 +188,7 @@ CanType TypeJoin::visitStructType(CanType second) {
184188

185189
// FIXME: When possible we should return a protocol or protocol
186190
// composition.
187-
return TheAnyType;
191+
return getAnyExistentialType();
188192
}
189193

190194
CanType TypeJoin::visitClassType(CanType second) {
@@ -240,7 +244,7 @@ CanType TypeJoin::visitMetatypeType(CanType second) {
240244
assert(First != second);
241245

242246
if (First->getKind() != second->getKind())
243-
return TheAnyType;
247+
return getAnyExistentialType();
244248

245249
auto firstInstance =
246250
First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
@@ -258,7 +262,7 @@ CanType TypeJoin::visitExistentialMetatypeType(CanType second) {
258262
assert(First != second);
259263

260264
if (First->getKind() != second->getKind())
261-
return TheAnyType;
265+
return getAnyExistentialType();
262266

263267
auto firstInstance =
264268
First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
@@ -276,7 +280,7 @@ CanType TypeJoin::visitExistentialType(CanType second) {
276280
assert(First != second);
277281

278282
if (First->getKind() != second->getKind())
279-
return TheAnyType;
283+
return getAnyExistentialType();
280284

281285
auto firstConstraint = First->castTo<ExistentialType>()
282286
->getConstraintType()->getCanonicalType();
@@ -293,7 +297,7 @@ CanType TypeJoin::visitExistentialType(CanType second) {
293297
CanType TypeJoin::visitModuleType(CanType second) {
294298
assert(First != second);
295299

296-
return TheAnyType;
300+
return getAnyExistentialType();
297301
}
298302

299303
CanType TypeJoin::visitDynamicSelfType(CanType second) {
@@ -312,7 +316,7 @@ CanType TypeJoin::visitDependentMemberType(CanType second) {
312316
assert(First != second);
313317

314318
if (First->getKind() != second->getKind())
315-
return TheAnyType;
319+
return getAnyExistentialType();
316320

317321
return Unimplemented;
318322
}
@@ -326,7 +330,7 @@ CanType TypeJoin::visitFunctionType(CanType second) {
326330
if (secondFnTy->getExtInfo().isNoEscape()) {
327331
return Nonexistent;
328332
} else {
329-
return TheAnyType;
333+
return getAnyExistentialType();
330334
}
331335
}
332336

@@ -362,7 +366,7 @@ CanType TypeJoin::visitGenericFunctionType(CanType second) {
362366
assert(First != second);
363367

364368
if (First->getKind() != second->getKind())
365-
return TheAnyType;
369+
return getAnyExistentialType();
366370

367371
return Unimplemented;
368372
}
@@ -482,7 +486,7 @@ CanType TypeJoin::visitBuiltinType(CanType second) {
482486
assert(First != second);
483487

484488
// BuiltinType with any non-equal type results in Any.
485-
return TheAnyType;
489+
return getAnyExistentialType();
486490
}
487491

488492
} // namespace

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5414,7 +5414,7 @@ static ValueDecl *addThunkForDependentTypes(FuncDecl *oldDecl,
54145414
// If the un-specialized function had a parameter with type "Any" preserve
54155415
// that parameter. Otherwise, use the new function parameter.
54165416
auto oldParamType = oldDecl->getParameters()->get(parameterIndex)->getType();
5417-
if (oldParamType->isEqual(newDecl->getASTContext().TheAnyType)) {
5417+
if (oldParamType->isEqual(newDecl->getASTContext().getAnyExistentialType())) {
54185418
updatedAnyParams = true;
54195419
auto newParam =
54205420
ParamDecl::cloneWithoutType(newDecl->getASTContext(), newFnParam);
@@ -5429,16 +5429,16 @@ static ValueDecl *addThunkForDependentTypes(FuncDecl *oldDecl,
54295429
// If we don't need this thunk, bail out.
54305430
if (!updatedAnyParams &&
54315431
!oldDecl->getResultInterfaceType()->isEqual(
5432-
oldDecl->getASTContext().TheAnyType))
5432+
oldDecl->getASTContext().getAnyExistentialType()))
54335433
return newDecl;
54345434

54355435
auto fixedParams =
54365436
ParameterList::create(newDecl->getASTContext(), fixedParameters);
54375437

54385438
Type fixedResultType;
54395439
if (oldDecl->getResultInterfaceType()->isEqual(
5440-
oldDecl->getASTContext().TheAnyType))
5441-
fixedResultType = oldDecl->getASTContext().TheAnyType;
5440+
oldDecl->getASTContext().getAnyExistentialType()))
5441+
fixedResultType = oldDecl->getASTContext().getAnyExistentialType();
54425442
else
54435443
fixedResultType = newDecl->getResultInterfaceType();
54445444

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8161,7 +8161,7 @@ Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
81618161
}
81628162
if (inherited.empty()) {
81638163
inherited.push_back(
8164-
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectType()));
8164+
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectConstraint()));
81658165
}
81668166
genericParamDecl->setInherited(Impl.SwiftContext.AllocateCopy(inherited));
81678167

0 commit comments

Comments
 (0)