Skip to content

Commit 1d47621

Browse files
committed
[CSSimplify] Merge binding inference logic with PackElementOf constraint simplification
It's only safe to infer element type from `PackElementOf` constraint when pattern type is fully resolved (because it can have pack element archetypes which should be mapped out of context), the same applies to the pattern type inference as well. Since constraints are re-activated every time a referenced type variable is bound, simplication logic can act as inference source by decaying into `Equal` constraints where pattern/element type are resolved via surrounding information first. (cherry picked from commit 9a395f0)
1 parent 9d80c4e commit 1d47621

File tree

2 files changed

+52
-87
lines changed

2 files changed

+52
-87
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,56 +1479,10 @@ void PotentialBindings::infer(Constraint *constraint) {
14791479
case ConstraintKind::BindTupleOfFunctionParams:
14801480
case ConstraintKind::ShapeOf:
14811481
case ConstraintKind::ExplicitGenericArguments:
1482+
case ConstraintKind::PackElementOf:
14821483
// Constraints from which we can't do anything.
14831484
break;
14841485

1485-
case ConstraintKind::PackElementOf: {
1486-
auto elementType = CS.simplifyType(constraint->getFirstType());
1487-
auto packType = CS.simplifyType(constraint->getSecondType());
1488-
1489-
if (elementType->isTypeVariableOrMember() && packType->isTypeVariableOrMember())
1490-
break;
1491-
1492-
auto *elementVar = elementType->getAs<TypeVariableType>();
1493-
auto *packVar = packType->getAs<TypeVariableType>();
1494-
1495-
if (elementVar == TypeVar && !packVar) {
1496-
// Produce a potential binding to the opened element archetype corresponding
1497-
// to the pack type.
1498-
auto shapeClass = packType->getReducedShape();
1499-
packType = packType->mapTypeOutOfContext();
1500-
auto *elementEnv = CS.getPackElementEnvironment(constraint->getLocator(),
1501-
shapeClass);
1502-
1503-
// Without an opened element environment, we cannot derive the
1504-
// element binding.
1505-
if (!elementEnv)
1506-
break;
1507-
1508-
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
1509-
assert(!elementType->is<PackType>());
1510-
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
1511-
1512-
break;
1513-
} else if (packVar == TypeVar && !elementVar) {
1514-
// Produce a potential binding to the pack archetype corresponding to
1515-
// the opened element type.
1516-
Type patternType;
1517-
auto *packEnv = CS.DC->getGenericEnvironmentOfContext();
1518-
if (!elementType->hasElementArchetype()) {
1519-
patternType = elementType;
1520-
} else {
1521-
patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1522-
}
1523-
1524-
addPotentialBinding({patternType, AllowedBindingKind::Exact, constraint});
1525-
1526-
break;
1527-
}
1528-
1529-
break;
1530-
}
1531-
15321486
// For now let's avoid inferring protocol requirements from
15331487
// this constraint, but in the future we could do that to
15341488
// to filter bindings.

lib/Sema/CSSimplify.cpp

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9002,67 +9002,78 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
90029002
return SolutionKind::Solved;
90039003
}
90049004

9005-
static Type lookThroughSingletonPackExpansion(Type ty) {
9006-
if (auto pack = ty->getAs<PackType>()) {
9007-
if (pack->getNumElements() == 1) {
9008-
if (auto expansion = pack->getElementType(0)->getAs<PackExpansionType>()) {
9009-
auto countType = expansion->getCountType();
9010-
if (countType->isEqual(expansion->getPatternType()))
9011-
return countType;
9012-
}
9013-
}
9014-
}
9015-
return ty;
9016-
}
9017-
90189005
ConstraintSystem::SolutionKind
90199006
ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
90209007
TypeMatchOptions flags,
90219008
ConstraintLocatorBuilder locator) {
90229009
auto elementType = simplifyType(first, flags);
9023-
auto packType = simplifyType(second, flags);
9010+
auto patternType = simplifyType(second, flags);
90249011

9025-
if (elementType->hasTypeVariable() || packType->hasTypeVariable()) {
9012+
auto formUnsolved = [&]() {
90269013
if (!flags.contains(TMF_GenerateConstraints))
90279014
return SolutionKind::Unsolved;
90289015

9029-
auto *loc = getConstraintLocator(locator);
90309016
addUnsolvedConstraint(
9031-
Constraint::create(*this, ConstraintKind::PackElementOf,
9032-
first, second, loc));
9017+
Constraint::create(*this, ConstraintKind::PackElementOf, first, second,
9018+
getConstraintLocator(locator)));
90339019

90349020
return SolutionKind::Solved;
9021+
};
9022+
9023+
// If neither side is fully resolved yet, there is nothing we can do.
9024+
if (elementType->hasTypeVariable() && patternType->hasTypeVariable())
9025+
return formUnsolved();
9026+
9027+
if (shouldAttemptFixes()) {
9028+
if (elementType->isPlaceholder() || patternType->isPlaceholder())
9029+
return SolutionKind::Solved;
90359030
}
90369031

9037-
// FIXME: I'm not sure this is actually necessary; I may only be seeing
9038-
// this because of something I've screwed up in element generic
9039-
// environments.
9040-
elementType = lookThroughSingletonPackExpansion(elementType);
9032+
// Let's try to resolve element type based on the pattern type.
9033+
if (!patternType->hasTypeVariable()) {
9034+
auto *loc = getConstraintLocator(locator);
9035+
auto shapeClass = patternType->getReducedShape();
9036+
patternType = patternType->mapTypeOutOfContext();
9037+
auto *elementEnv = getPackElementEnvironment(loc, shapeClass);
90419038

9042-
// This constraint only exists to vend bindings.
9043-
auto *packEnv = DC->getGenericEnvironmentOfContext();
9039+
// Without an opened element environment, we cannot derive the
9040+
// element binding.
9041+
if (!elementEnv) {
9042+
if (!shouldAttemptFixes())
9043+
return SolutionKind::Error;
90449044

9045-
// Map element archetypes to the pack context to check for equality.
9046-
if (elementType->hasElementArchetype()) {
9047-
auto mappedPack = packEnv->mapElementTypeIntoPackContext(elementType);
9048-
return (packType->isEqual(mappedPack) ?
9049-
SolutionKind::Solved : SolutionKind::Error);
9050-
}
9045+
// `each` was applied to a concrete type.
9046+
if (!shapeClass->is<PackArchetypeType>()) {
9047+
if (recordFix(AllowInvalidPackElement::create(*this, patternType, loc)))
9048+
return SolutionKind::Error;
9049+
}
90519050

9052-
// Pack expansions can have concrete pattern types. In this case, the pack
9053-
// type and element type will be equal.
9054-
if (packType->isEqual(elementType)) {
9055-
return SolutionKind::Solved;
9056-
}
9051+
// Only other posibility is that there is a shape mismatch between
9052+
// elements of the pack expansion pattern which is detected separately.
90579053

9058-
if (shouldAttemptFixes()) {
9059-
auto *loc = getConstraintLocator(locator);
9060-
if (elementType->isPlaceholder() ||
9061-
!recordFix(AllowInvalidPackElement::create(*this, packType, loc)))
9054+
recordAnyTypeVarAsPotentialHole(elementType);
90629055
return SolutionKind::Solved;
9056+
}
9057+
9058+
auto expectedElementTy =
9059+
elementEnv->mapPackTypeIntoElementContext(patternType);
9060+
assert(!expectedElementTy->is<PackType>());
9061+
9062+
addConstraint(ConstraintKind::Equal, elementType, expectedElementTy,
9063+
locator);
9064+
return SolutionKind::Solved;
90639065
}
90649066

9065-
return SolutionKind::Error;
9067+
// Otherwise we are inferred or checking pattern type.
9068+
9069+
auto *packEnv = DC->getGenericEnvironmentOfContext();
9070+
9071+
// Map element archetypes to the pack context to check for equality.
9072+
if (elementType->hasElementArchetype())
9073+
elementType = packEnv->mapElementTypeIntoPackContext(elementType);
9074+
9075+
addConstraint(ConstraintKind::Equal, elementType, patternType, locator);
9076+
return SolutionKind::Solved;
90669077
}
90679078

90689079
static bool isForKeyPathSubscript(ConstraintSystem &cs,

0 commit comments

Comments
 (0)