[TypeChecker] Require a coercion if result of protocol member access would loose information

Accessing members on the protocol could result in existential opening and subsequence
result erasure, which requires explicit coercion if there is any loss of generic requirements.
This commit is contained in:
Pavel Yaskevich
2022-04-22 14:45:13 -07:00
parent 73b16ba4ea
commit 773ea6b10c
5 changed files with 132 additions and 44 deletions

View File

@@ -2296,11 +2296,30 @@ ConstraintSystem::getTypeOfMemberReference(
baseObjTy->isExistentialType() && outerDC->getSelfProtocolDecl() &&
// If there are no type variables, there were no references to 'Self'.
type->hasTypeVariable()) {
auto getResultType = [](Type type) {
if (auto *funcTy = type->getAs<FunctionType>())
return funcTy->getResult();
return type;
};
auto nonErasedResultTy = getResultType(type);
const auto selfGP = cast<GenericTypeParamType>(
outerDC->getSelfInterfaceType()->getCanonicalType());
auto openedTypeVar = replacements.lookup(selfGP);
type = typeEraseOpenedExistentialReference(type, baseObjTy, openedTypeVar,
TypePosition::Covariant);
if (!hasFixFor(locator) &&
AddExplicitExistentialCoercion::isRequired(
*this, nonErasedResultTy,
[&](TypeVariableType *typeVar) {
return openedTypeVar == typeVar ? baseObjTy : Optional<Type>();
},
locator)) {
recordFix(AddExplicitExistentialCoercion::create(
*this, getResultType(type), locator));
}
}
// Construct an idealized parameter type of the initializer associated