Sema: Better handling of type members in getTypeOfMemberReference()

We don't actually want to open the type; instead, calculate the
substituted member type using substMemberTypeWithBase(), which
will return an unbound generic type if the member is a generic
nominal or type alias, and then it open it with openUnboundGenericType().

This is NFC for now, but I need generic typealiases to come in as
UnboundGenericTypes here in a subsequent patch.
This commit is contained in:
Slava Pestov
2017-05-22 00:32:05 -07:00
parent 1c4f299a3c
commit c23686f5c0

View File

@@ -1005,17 +1005,24 @@ ConstraintSystem::getTypeOfMemberReference(
if (auto *alias = dyn_cast<TypeAliasDecl>(value)) {
if (baseObjTy->isExistentialType()) {
auto memberTy = alias->getDeclaredInterfaceType();
// If we end up with a protocol typealias here, it's underlying
// type must be fully concrete.
assert(!memberTy->hasTypeParameter());
auto openedType = FunctionType::get(baseObjTy, memberTy);
return { openedType, memberTy };
}
}
// Handle associated type lookup as a special case, horribly.
// FIXME: This is an awful hack.
if (isa<AssociatedTypeDecl>(value)) {
// Refer to a member of the archetype directly.
auto archetype = baseObjTy->castTo<ArchetypeType>();
Type memberTy = archetype->getNestedType(value->getName());
if (auto *typeDecl = dyn_cast<TypeDecl>(value)) {
assert(!isa<ModuleDecl>(typeDecl) && "Nested module?");
auto memberTy = TC.substMemberTypeWithBase(DC->getParentModule(),
typeDecl, baseObjTy);
// Open the type if it was a reference to a generic type.
memberTy = openUnboundGenericType(memberTy, locator);
// Wrap it in a metatype.
memberTy = MetatypeType::get(memberTy);
auto openedType = FunctionType::get(baseObjTy, memberTy);
@@ -1046,8 +1053,7 @@ ConstraintSystem::getTypeOfMemberReference(
} else {
// If we're not coming from something function-like, prepend the type
// for 'self' to the type.
assert(isa<AbstractStorageDecl>(value) ||
isa<TypeDecl>(value));
assert(isa<AbstractStorageDecl>(value));
openedType = TC.getUnopenedTypeOfReference(value, baseTy, useDC, base,
/*wantInterfaceType=*/true);