Skip to content

Commit 9a395f0

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.
1 parent fd060f5 commit 9a395f0

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
@@ -8998,67 +8998,78 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
89988998
return SolutionKind::Solved;
89998999
}
90009000

9001-
static Type lookThroughSingletonPackExpansion(Type ty) {
9002-
if (auto pack = ty->getAs<PackType>()) {
9003-
if (pack->getNumElements() == 1) {
9004-
if (auto expansion = pack->getElementType(0)->getAs<PackExpansionType>()) {
9005-
auto countType = expansion->getCountType();
9006-
if (countType->isEqual(expansion->getPatternType()))
9007-
return countType;
9008-
}
9009-
}
9010-
}
9011-
return ty;
9012-
}
9013-
90149001
ConstraintSystem::SolutionKind
90159002
ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
90169003
TypeMatchOptions flags,
90179004
ConstraintLocatorBuilder locator) {
90189005
auto elementType = simplifyType(first, flags);
9019-
auto packType = simplifyType(second, flags);
9006+
auto patternType = simplifyType(second, flags);
90209007

9021-
if (elementType->hasTypeVariable() || packType->hasTypeVariable()) {
9008+
auto formUnsolved = [&]() {
90229009
if (!flags.contains(TMF_GenerateConstraints))
90239010
return SolutionKind::Unsolved;
90249011

9025-
auto *loc = getConstraintLocator(locator);
90269012
addUnsolvedConstraint(
9027-
Constraint::create(*this, ConstraintKind::PackElementOf,
9028-
first, second, loc));
9013+
Constraint::create(*this, ConstraintKind::PackElementOf, first, second,
9014+
getConstraintLocator(locator)));
90299015

90309016
return SolutionKind::Solved;
9017+
};
9018+
9019+
// If neither side is fully resolved yet, there is nothing we can do.
9020+
if (elementType->hasTypeVariable() && patternType->hasTypeVariable())
9021+
return formUnsolved();
9022+
9023+
if (shouldAttemptFixes()) {
9024+
if (elementType->isPlaceholder() || patternType->isPlaceholder())
9025+
return SolutionKind::Solved;
90319026
}
90329027

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

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

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

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

9054-
if (shouldAttemptFixes()) {
9055-
auto *loc = getConstraintLocator(locator);
9056-
if (elementType->isPlaceholder() ||
9057-
!recordFix(AllowInvalidPackElement::create(*this, packType, loc)))
9050+
recordAnyTypeVarAsPotentialHole(elementType);
90589051
return SolutionKind::Solved;
9052+
}
9053+
9054+
auto expectedElementTy =
9055+
elementEnv->mapPackTypeIntoElementContext(patternType);
9056+
assert(!expectedElementTy->is<PackType>());
9057+
9058+
addConstraint(ConstraintKind::Equal, elementType, expectedElementTy,
9059+
locator);
9060+
return SolutionKind::Solved;
90599061
}
90609062

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

90649075
static bool isForKeyPathSubscript(ConstraintSystem &cs,

0 commit comments

Comments
 (0)