Skip to content

Commit 429488f

Browse files
committed
[Sema] Use ExistentialType for Any and AnyObject.
1 parent d7a60df commit 429488f

26 files changed

+139
-84
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: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5444,17 +5444,30 @@ struct ExistentialTypeGeneralization {
54445444
class ExistentialType final : public TypeBase {
54455445
Type ConstraintType;
54465446

5447+
/// Whether to print this existential type with the 'any' keyword,
5448+
/// e.g. in diagnostics.
5449+
///
5450+
/// Any and AnyObject need not use 'any', and they are printed
5451+
/// in diagnostics without 'any' unless wrapped in MetatypeType.
5452+
/// This field should only be used by TypePrinter.
5453+
bool PrintWithAny;
5454+
54475455
ExistentialType(Type constraintType,
5456+
bool printWithAny,
54485457
const ASTContext *canonicalContext,
54495458
RecursiveTypeProperties properties)
54505459
: TypeBase(TypeKind::Existential, canonicalContext, properties),
5451-
ConstraintType(constraintType) {}
5460+
ConstraintType(constraintType), PrintWithAny(printWithAny) {}
54525461

54535462
public:
5454-
static Type get(Type constraint, bool forceExistential = false);
5463+
static Type get(Type constraint);
54555464

54565465
Type getConstraintType() const { return ConstraintType; }
54575466

5467+
bool shouldPrintWithAny() const { return PrintWithAny; }
5468+
5469+
void forcePrintWithAny(bool value) { PrintWithAny = value; }
5470+
54585471
bool requiresClass() const {
54595472
if (auto protocol = ConstraintType->getAs<ProtocolType>())
54605473
return protocol->requiresClass();

lib/AST/ASTContext.cpp

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

962-
CanType ASTContext::getAnyObjectType() const {
962+
CanType ASTContext::getAnyExistentialType() const {
963+
return ExistentialType::get(TheAnyType)->getCanonicalType();
964+
}
965+
966+
CanType ASTContext::getAnyObjectConstraint() const {
963967
if (getImpl().AnyObjectType) {
964968
return getImpl().AnyObjectType;
965969
}
@@ -970,6 +974,11 @@ CanType ASTContext::getAnyObjectType() const {
970974
return getImpl().AnyObjectType;
971975
}
972976

977+
CanType ASTContext::getAnyObjectType() const {
978+
return ExistentialType::get(getAnyObjectConstraint())
979+
->getCanonicalType();
980+
}
981+
973982
#define KNOWN_SDK_TYPE_DECL(MODULE, NAME, DECLTYPE, GENERIC_ARGS) \
974983
DECLTYPE *ASTContext::get##NAME##Decl() const { \
975984
if (!getImpl().NAME##Decl) { \
@@ -4261,20 +4270,18 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, Type Parent,
42614270
RecursiveTypeProperties properties)
42624271
: NominalType(TypeKind::Protocol, &Ctx, TheDecl, Parent, properties) { }
42634272

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

42764279
assert(constraint->isConstraintType());
42774280

4281+
bool printWithAny = true;
4282+
if (constraint->isEqual(C.TheAnyType) || constraint->isAnyObject())
4283+
printWithAny = false;
4284+
42784285
auto properties = constraint->getRecursiveProperties();
42794286
if (constraint->is<ParameterizedProtocolType>())
42804287
properties |= RecursiveTypeProperties::HasParameterizedExistential;
@@ -4285,7 +4292,7 @@ Type ExistentialType::get(Type constraint, bool forceExistential) {
42854292
return entry;
42864293

42874294
const ASTContext *canonicalContext = constraint->isCanonical() ? &C : nullptr;
4288-
return entry = new (C, arena) ExistentialType(constraint,
4295+
return entry = new (C, arena) ExistentialType(constraint, printWithAny,
42894296
canonicalContext,
42904297
properties);
42914298
}

lib/AST/ASTPrinter.cpp

Lines changed: 18 additions & 11 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,6 +5632,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56325632
}
56335633

56345634
Type instanceType = T->getInstanceType();
5635+
bool didPrintInstanceType = false;
56355636
if (Options.PrintExplicitAny) {
56365637
if (T->is<ExistentialMetatypeType>()) {
56375638
Printer << "any ";
@@ -5645,18 +5646,24 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
56455646

56465647
return type;
56475648
});
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);
5649+
} else if (auto existential = instanceType->getAs<ExistentialType>()) {
5650+
// The 'any' keyword is needed to distinguish between existential
5651+
// metatypes and singleton metatypes. However, 'any' usually isn't
5652+
// printed for Any and AnyObject, because it's unnecessary to write
5653+
// 'any' with these specific constraints. Set a bit on the existential
5654+
// type to force printing with 'any' for metatypes. This bit doesn't
5655+
// matter for anything other than printing.
5656+
if (!existential->shouldPrintWithAny()) {
5657+
existential->forcePrintWithAny(true);
5658+
printWithParensIfNotSimple(existential);
5659+
existential->forcePrintWithAny(false);
5660+
didPrintInstanceType = true;
5661+
}
56565662
}
56575663
}
56585664

5659-
printWithParensIfNotSimple(instanceType);
5665+
if (!didPrintInstanceType)
5666+
printWithParensIfNotSimple(instanceType);
56605667

56615668
// We spell normal metatypes of existential types as .Protocol.
56625669
if (isa<MetatypeType>(T) &&
@@ -6278,7 +6285,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
62786285
}
62796286

62806287
void visitExistentialType(ExistentialType *T) {
6281-
if (Options.PrintExplicitAny)
6288+
if (Options.PrintExplicitAny && T->shouldPrintWithAny())
62826289
Printer << "any ";
62836290

62846291
// FIXME: The desugared type is used here only to support

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: 17 additions & 13 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
}
@@ -412,7 +416,7 @@ CanType TypeJoin::visitProtocolCompositionType(CanType second) {
412416
if (fnTy && fnTy->getExtInfo().isNoEscape())
413417
return Nonexistent;
414418

415-
return TheAnyType;
419+
return getAnyExistentialType();
416420
}
417421

418422
assert(First != second);
@@ -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
@@ -6520,7 +6520,7 @@ Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
65206520
}
65216521
if (inherited.empty()) {
65226522
inherited.push_back(
6523-
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectType()));
6523+
TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectConstraint()));
65246524
}
65256525
genericParamDecl->setInherited(Impl.SwiftContext.AllocateCopy(inherited));
65266526

0 commit comments

Comments
 (0)