Sema: Fix deep equality matching for parameterized protocol types

Fixes rdar://problem/98356057.
This commit is contained in:
Slava Pestov
2022-08-09 23:44:03 -04:00
parent cb0721fa6e
commit 11eb11833f
5 changed files with 103 additions and 19 deletions

View File

@@ -3286,7 +3286,41 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
}
// Handle existential types.
if (type1->isExistentialType() && type2->isExistentialType()) {
if (auto *existential1 = type1->getAs<ExistentialType>()) {
auto existential2 = type2->castTo<ExistentialType>();
auto result = matchTypes(existential1->getConstraintType(),
existential2->getConstraintType(),
ConstraintKind::Bind, subflags,
locator.withPathElement(
ConstraintLocator::ExistentialConstraintType));
if (result.isFailure())
return result;
return getTypeMatchSuccess();
}
// Arguments of parameterized protocol types have to match on the nose.
if (auto ppt1 = type1->getAs<ParameterizedProtocolType>()) {
auto ppt2 = type2->castTo<ParameterizedProtocolType>();
auto result = matchTypes(ppt1->getBaseType(),
ppt2->getBaseType(),
ConstraintKind::Bind, subflags,
locator.withPathElement(
ConstraintLocator::ParentType));
if (result.isFailure())
return result;
return matchDeepTypeArguments(*this, subflags,
ppt1->getArgs(),
ppt2->getArgs(),
locator);
}
if (type1->isExistentialType()) {
auto layout1 = type1->getExistentialLayout();
auto layout2 = type2->getExistentialLayout();
@@ -3309,24 +3343,16 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
if (!layout1.explicitSuperclass || !layout2.explicitSuperclass)
return getTypeMatchFailure(locator);
auto subLocator = locator.withPathElement(
ConstraintLocator::ProtocolCompositionSuperclassType);
auto result = matchTypes(layout1.explicitSuperclass,
layout2.explicitSuperclass,
ConstraintKind::Bind, subflags,
locator.withPathElement(
ConstraintLocator::ExistentialSuperclassType));
subLocator);
if (result.isFailure())
return result;
}
// Arguments of parameterized protocol types have to match on the nose.
if (auto ppt1 = type1->getAs<ParameterizedProtocolType>()) {
auto ppt2 = type2->castTo<ParameterizedProtocolType>();
return matchDeepTypeArguments(*this, subflags,
ppt1->getArgs(),
ppt2->getArgs(),
locator);
}
return getTypeMatchSuccess();
}
@@ -6367,7 +6393,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
// If we are matching types for equality, we might still have
// type variables inside the protocol composition's superclass
// constraint.
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
if (desugar1->getKind() == desugar2->getKind())
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
break;
default: