Skip to content

Commit a2328b0

Browse files
committed
[Type Resolution] Resolve (any P.Type).Type as the metatype of an
existential metatype. Until we model ExistentialMetatypeType as ExistentialType(MetatypeType), type resolution needs to look through the instance type repr when resolving a metatype. Otherwise, there's no way to distinguish between P.Type.Type, which is an existential metatype, and (any P.Type).Type, which is the static metatype of an existential metatype.
1 parent 4ebf04a commit a2328b0

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4008,6 +4008,30 @@ NeverNullType TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr,
40084008
NeverNullType
40094009
TypeResolver::buildMetatypeType(MetatypeTypeRepr *repr, Type instanceType,
40104010
Optional<MetatypeRepresentation> storedRepr) {
4011+
// If the instance type is an existential metatype, figure out if
4012+
// the syntax is of the form '(any <protocol metatype>).Type'. In
4013+
// this case, type resolution should produce the static metatype
4014+
// of that existential metatype, versus another existential metatype
4015+
// via the old '<protocol metatype>.Type' syntax.
4016+
if (instanceType->is<ExistentialMetatypeType>()) {
4017+
// First, look for the paren type.
4018+
auto *tuple = dyn_cast<TupleTypeRepr>(repr->getBase());
4019+
if (tuple && tuple->isParenType()) {
4020+
// Then, look through parens for the 'any' keyword.
4021+
auto *element = tuple->getWithoutParens();
4022+
if (auto *existential = dyn_cast<ExistentialTypeRepr>(element)) {
4023+
// Finally, look for a constraint ending with '.Type'. Assume the
4024+
// base is a protocol, otherwise resolveExistentialType would
4025+
// have emitted an error message and returned the concrete type
4026+
// instead of an existential metatype.
4027+
auto *constraint = existential->getConstraint()->getWithoutParens();
4028+
if (isa<MetatypeTypeRepr>(constraint)) {
4029+
return MetatypeType::get(instanceType, storedRepr);
4030+
}
4031+
}
4032+
}
4033+
}
4034+
40114035
if (instanceType->isAnyExistentialType() &&
40124036
!instanceType->is<ExistentialType>()) {
40134037
// TODO: diagnose invalid representations?

test/type/explicit_existential.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,9 @@ func testAnyFixIt() {
314314
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc.Type)?'}}{{10-28=(any HasAssoc.Type)?}}
315315
let _: any HasAssoc.Type? = nil
316316
}
317+
318+
func testNestedMetatype() {
319+
let _: (any P.Type).Type = (any P.Type).self
320+
let _: (any (P.Type)).Type = (any P.Type).self
321+
let _: ((any (P.Type))).Type = (any P.Type).self
322+
}

0 commit comments

Comments
 (0)