Skip to content

Commit 0053526

Browse files
authored
Merge pull request #41909 from hborla/existential-any-anyobject
[Sema] Use `ExistentialType` for `Any` and `AnyObject`.
2 parents 789545d + 06c4717 commit 0053526

26 files changed

+152
-100
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
@@ -5451,17 +5451,35 @@ struct ExistentialTypeGeneralization {
54515451
class ExistentialType final : public TypeBase {
54525452
Type ConstraintType;
54535453

5454+
/// Whether to print this existential type with the 'any' keyword,
5455+
/// e.g. in diagnostics.
5456+
///
5457+
/// Any and AnyObject need not use 'any', and they are printed
5458+
/// in diagnostics without 'any' unless wrapped in MetatypeType.
5459+
/// This field should only be used by TypePrinter.
5460+
bool PrintWithAny;
5461+
54545462
ExistentialType(Type constraintType,
5463+
bool printWithAny,
54555464
const ASTContext *canonicalContext,
54565465
RecursiveTypeProperties properties)
54575466
: TypeBase(TypeKind::Existential, canonicalContext, properties),
5458-
ConstraintType(constraintType) {}
5467+
ConstraintType(constraintType), PrintWithAny(printWithAny) {}
54595468

54605469
public:
5461-
static Type get(Type constraint, bool forceExistential = false);
5470+
static Type get(Type constraint);
54625471

54635472
Type getConstraintType() const { return ConstraintType; }
54645473

5474+
bool shouldPrintWithAny() const { return PrintWithAny; }
5475+
5476+
void forcePrintWithAny(llvm::function_ref<void(Type)> print) {
5477+
bool oldValue = PrintWithAny;
5478+
PrintWithAny = true;
5479+
print(this);
5480+
PrintWithAny = oldValue;
5481+
}
5482+
54655483
bool requiresClass() const {
54665484
if (auto protocol = ConstraintType->getAs<ProtocolType>())
54675485
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) { \
@@ -4258,20 +4267,18 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, Type Parent,
42584267
RecursiveTypeProperties properties)
42594268
: NominalType(TypeKind::Protocol, &Ctx, TheDecl, Parent, properties) { }
42604269

4261-
Type ExistentialType::get(Type constraint, bool forceExistential) {
4270+
Type ExistentialType::get(Type constraint) {
42624271
auto &C = constraint->getASTContext();
4263-
if (!forceExistential) {
4264-
// FIXME: Any and AnyObject don't yet use ExistentialType.
4265-
if (constraint->isAny() || constraint->isAnyObject())
4266-
return constraint;
4267-
4268-
// ExistentialMetatypeType is already an existential type.
4269-
if (constraint->is<ExistentialMetatypeType>())
4270-
return constraint;
4271-
}
4272+
// ExistentialMetatypeType is already an existential type.
4273+
if (constraint->is<ExistentialMetatypeType>())
4274+
return constraint;
42724275

42734276
assert(constraint->isConstraintType());
42744277

4278+
bool printWithAny = true;
4279+
if (constraint->isEqual(C.TheAnyType) || constraint->isAnyObject())
4280+
printWithAny = false;
4281+
42754282
auto properties = constraint->getRecursiveProperties();
42764283
if (constraint->is<ParameterizedProtocolType>())
42774284
properties |= RecursiveTypeProperties::HasParameterizedExistential;
@@ -4282,7 +4289,7 @@ Type ExistentialType::get(Type constraint, bool forceExistential) {
42824289
return entry;
42834290

42844291
const ASTContext *canonicalContext = constraint->isCanonical() ? &C : nullptr;
4285-
return entry = new (C, arena) ExistentialType(constraint,
4292+
return entry = new (C, arena) ExistentialType(constraint, printWithAny,
42864293
canonicalContext,
42874294
properties);
42884295
}

lib/AST/ASTPrinter.cpp

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5196,7 +5196,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
51965196
llvm_unreachable("bad opaque-return-type printing mode");
51975197
}
51985198
} else if (auto existential = dyn_cast<ExistentialType>(T.getPointer())) {
5199-
if (!Options.PrintExplicitAny)
5199+
if (!Options.PrintExplicitAny || !existential->shouldPrintWithAny())
52005200
return isSimpleUnderPrintOptions(existential->getConstraintType());
52015201
} else if (auto existential = dyn_cast<ExistentialMetatypeType>(T.getPointer())) {
52025202
if (!Options.PrintExplicitAny)
@@ -5632,31 +5632,30 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56325632
}
56335633

56345634
Type instanceType = T->getInstanceType();
5635-
if (Options.PrintExplicitAny) {
5636-
if (T->is<ExistentialMetatypeType>()) {
5637-
Printer << "any ";
5638-
5639-
// FIXME: We need to replace nested existential metatypes so that
5640-
// we don't print duplicate 'any'. This will be unnecessary once
5641-
// ExistentialMetatypeType is split into ExistentialType(MetatypeType).
5642-
instanceType = Type(instanceType).transform([](Type type) -> Type {
5643-
if (auto existential = type->getAs<ExistentialMetatypeType>())
5644-
return MetatypeType::get(existential->getInstanceType());
5645-
5646-
return type;
5647-
});
5648-
} else if (instanceType->isAny() || instanceType->isAnyObject()) {
5649-
// FIXME: 'any' is needed to distinguish between '(any Any).Type'
5650-
// and 'any Any.Type'. However, this combined with the above hack
5651-
// to replace nested existential metatypes with metatypes causes
5652-
// a bug in printing nested existential metatypes for Any and AnyObject,
5653-
// e.g. 'any (any Any).Type.Type'. This will be fixed by using
5654-
// ExistentialType for Any and AnyObject.
5655-
instanceType = ExistentialType::get(instanceType, /*forceExistential=*/true);
5656-
}
5657-
}
5635+
if (Options.PrintExplicitAny && T->is<ExistentialMetatypeType>()) {
5636+
Printer << "any ";
5637+
5638+
// FIXME: We need to replace nested existential metatypes so that
5639+
// we don't print duplicate 'any'. This will be unnecessary once
5640+
// ExistentialMetatypeType is split into ExistentialType(MetatypeType).
5641+
printWithParensIfNotSimple(instanceType.transform([](Type type) -> Type {
5642+
if (auto existential = type->getAs<ExistentialMetatypeType>())
5643+
return MetatypeType::get(existential->getInstanceType());
56585644

5659-
printWithParensIfNotSimple(instanceType);
5645+
return type;
5646+
}));
5647+
} else if (T->is<MetatypeType>() && instanceType->is<ExistentialType>()) {
5648+
// The 'any' keyword is needed to distinguish between existential
5649+
// metatypes and singleton metatypes. However, 'any' usually isn't
5650+
// printed for Any and AnyObject, because it's unnecessary to write
5651+
// 'any' with these specific constraints. Force printing with 'any'
5652+
// for the existential instance type in this case.
5653+
instanceType->getAs<ExistentialType>()->forcePrintWithAny([&](Type ty) {
5654+
printWithParensIfNotSimple(ty);
5655+
});
5656+
} else {
5657+
printWithParensIfNotSimple(instanceType);
5658+
}
56605659

56615660
// We spell normal metatypes of existential types as .Protocol.
56625661
if (isa<MetatypeType>(T) &&
@@ -6278,15 +6277,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
62786277
}
62796278

62806279
void visitExistentialType(ExistentialType *T) {
6281-
if (Options.PrintExplicitAny)
6280+
if (Options.PrintExplicitAny && T->shouldPrintWithAny())
62826281
Printer << "any ";
62836282

62846283
// FIXME: The desugared type is used here only to support
62856284
// existential types with protocol typealiases in Swift
62866285
// interfaces. Verifying that the underlying type of a
62876286
// protocol typealias is a constriant type is fundamentally
62886287
// circular, so the desugared type should be written in source.
6289-
if (Options.DesugarExistentialConstraint) {
6288+
if (Options.DesugarExistentialConstraint && !T->isAnyObject()) {
62906289
visit(T->getConstraintType()->getDesugaredType());
62916290
} else {
62926291
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
@@ -2860,7 +2860,7 @@ static Type mapSignatureFunctionType(ASTContext &ctx, Type type,
28602860
// Functions and subscripts cannot overload differing only in opaque return
28612861
// types. Replace the opaque type with `Any`.
28622862
if (type->is<OpaqueTypeArchetypeType>()) {
2863-
type = ProtocolCompositionType::get(ctx, {}, /*hasAnyObject*/ false);
2863+
type = ctx.getAnyExistentialType();
28642864
}
28652865

28662866
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
@@ -5636,7 +5636,7 @@ static ValueDecl *addThunkForDependentTypes(FuncDecl *oldDecl,
56365636
// If the un-specialized function had a parameter with type "Any" preserve
56375637
// that parameter. Otherwise, use the new function parameter.
56385638
auto oldParamType = oldDecl->getParameters()->get(parameterIndex)->getType();
5639-
if (oldParamType->isEqual(newDecl->getASTContext().TheAnyType)) {
5639+
if (oldParamType->isEqual(newDecl->getASTContext().getAnyExistentialType())) {
56405640
updatedAnyParams = true;
56415641
auto newParam =
56425642
ParamDecl::cloneWithoutType(newDecl->getASTContext(), newFnParam);
@@ -5651,16 +5651,16 @@ static ValueDecl *addThunkForDependentTypes(FuncDecl *oldDecl,
56515651
// If we don't need this thunk, bail out.
56525652
if (!updatedAnyParams &&
56535653
!oldDecl->getResultInterfaceType()->isEqual(
5654-
oldDecl->getASTContext().TheAnyType))
5654+
oldDecl->getASTContext().getAnyExistentialType()))
56555655
return newDecl;
56565656

56575657
auto fixedParams =
56585658
ParameterList::create(newDecl->getASTContext(), fixedParameters);
56595659

56605660
Type fixedResultType;
56615661
if (oldDecl->getResultInterfaceType()->isEqual(
5662-
oldDecl->getASTContext().TheAnyType))
5663-
fixedResultType = oldDecl->getASTContext().TheAnyType;
5662+
oldDecl->getASTContext().getAnyExistentialType()))
5663+
fixedResultType = oldDecl->getASTContext().getAnyExistentialType();
56645664
else
56655665
fixedResultType = newDecl->getResultInterfaceType();
56665666

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6496,7 +6496,7 @@ Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
64966496
}
64976497
if (inherited.empty()) {
64986498
inherited.push_back(
6499-
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectType()));
6499+
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectConstraint()));
65006500
}
65016501
genericParamDecl->setInherited(Impl.SwiftContext.AllocateCopy(inherited));
65026502

0 commit comments

Comments
 (0)