When opening the type of a member reference for a given overload, and the context of the self type is a class-constrained existential, do not automatically wrap the self type in an inout. Doing so leads to mismatched expectations during constraint application, which will result in a compiler crash. (rdar://problem/22012606)

Swift SVN r30724
This commit is contained in:
Joe Pamer
2015-07-28 21:12:21 +00:00
parent 3e9357a9bb
commit d4e165688b
2 changed files with 27 additions and 1 deletions

View File

@@ -1140,6 +1140,7 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
// Open the type of the generic function or member of a generic type.
Type openedType;
auto isClassBoundExistential = false;
llvm::DenseMap<CanType, TypeVariableType *> replacements;
if (auto genericFn = value->getInterfaceType()->getAs<GenericFunctionType>()){
openedType = openType(genericFn, locator, replacements, dc,
@@ -1162,6 +1163,15 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
// Determine the object type of 'self'.
auto nominal = value->getDeclContext()->getDeclaredTypeOfContext()
->getAnyNominal();
// We want to track if the generic context is represented by a
// class-bound existential so we won't inappropriately wrap the
// self type in an inout later on.
if (auto metatype = nominal->getType()->getAs<AnyMetatypeType>()) {
isClassBoundExistential = metatype->getInstanceType()->
isClassExistentialType();
}
if (dc->isProtocolOrProtocolExtensionContext()) {
// Retrieve the type variable for 'Self'.
selfTy = replacements[dc->getProtocolSelf()->getDeclaredType()
@@ -1184,7 +1194,9 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
if (!isa<AbstractFunctionDecl>(value) && !isa<EnumElementDecl>(value)) {
// If self is a struct, properly qualify it based on our base
// qualification. If we have an lvalue coming in, we expect an inout.
if (!selfTy->hasReferenceSemantics() && baseTy->is<LValueType>())
if (!isClassBoundExistential &&
!selfTy->hasReferenceSemantics() &&
baseTy->is<LValueType>())
selfTy = InOutType::get(selfTy);
openedType = FunctionType::get(selfTy, openedType);