Skip to content

Commit 8930d58

Browse files
committed
[Sema] Use ExistentialType for Any and AnyObject.
1 parent 700f776 commit 8930d58

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
@@ -5398,17 +5398,30 @@ 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(bool value) { PrintWithAny = value; }
5424+
54125425
bool requiresClass() const {
54135426
if (auto protocol = ConstraintType->getAs<ProtocolType>())
54145427
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: 18 additions & 11 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,6 +5581,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55815581
}
55825582

55835583
Type instanceType = T->getInstanceType();
5584+
bool didPrintInstanceType = false;
55845585
if (Options.PrintExplicitAny) {
55855586
if (T->is<ExistentialMetatypeType>()) {
55865587
Printer << "any ";
@@ -5594,18 +5595,24 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55945595

55955596
return type;
55965597
});
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);
5598+
} else if (auto existential = instanceType->getAs<ExistentialType>()) {
5599+
// The 'any' keyword is needed to distinguish between existential
5600+
// metatypes and singleton metatypes. However, 'any' usually isn't
5601+
// printed for Any and AnyObject, because it's unnecessary to write
5602+
// 'any' with these specific constraints. Set a bit on the existential
5603+
// type to force printing with 'any' for metatypes. This bit doesn't
5604+
// matter for anything other than printing.
5605+
if (!existential->shouldPrintWithAny()) {
5606+
existential->forcePrintWithAny(true);
5607+
printWithParensIfNotSimple(existential);
5608+
existential->forcePrintWithAny(false);
5609+
didPrintInstanceType = true;
5610+
}
56055611
}
56065612
}
56075613

5608-
printWithParensIfNotSimple(instanceType);
5614+
if (!didPrintInstanceType)
5615+
printWithParensIfNotSimple(instanceType);
56095616

56105617
// We spell normal metatypes of existential types as .Protocol.
56115618
if (isa<MetatypeType>(T) &&
@@ -6217,7 +6224,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
62176224
}
62186225

62196226
void visitExistentialType(ExistentialType *T) {
6220-
if (Options.PrintExplicitAny)
6227+
if (Options.PrintExplicitAny && T->shouldPrintWithAny())
62216228
Printer << "any ";
62226229

62236230
// 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
@@ -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: 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
@@ -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

0 commit comments

Comments
 (0)