Skip to content

Commit bb7f01c

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 0e4ef95 commit bb7f01c

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
@@ -9015,67 +9015,78 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
90159015
return SolutionKind::Solved;
90169016
}
90179017

9018-
static Type lookThroughSingletonPackExpansion(Type ty) {
9019-
if (auto pack = ty->getAs<PackType>()) {
9020-
if (pack->getNumElements() == 1) {
9021-
if (auto expansion = pack->getElementType(0)->getAs<PackExpansionType>()) {
9022-
auto countType = expansion->getCountType();
9023-
if (countType->isEqual(expansion->getPatternType()))
9024-
return countType;
9025-
}
9026-
}
9027-
}
9028-
return ty;
9029-
}
9030-
90319018
ConstraintSystem::SolutionKind
90329019
ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
90339020
TypeMatchOptions flags,
90349021
ConstraintLocatorBuilder locator) {
90359022
auto elementType = simplifyType(first, flags);
9036-
auto packType = simplifyType(second, flags);
9023+
auto patternType = simplifyType(second, flags);
90379024

9038-
if (elementType->hasTypeVariable() || packType->hasTypeVariable()) {
9025+
auto formUnsolved = [&]() {
90399026
if (!flags.contains(TMF_GenerateConstraints))
90409027
return SolutionKind::Unsolved;
90419028

9042-
auto *loc = getConstraintLocator(locator);
90439029
addUnsolvedConstraint(
9044-
Constraint::create(*this, ConstraintKind::PackElementOf,
9045-
first, second, loc));
9030+
Constraint::create(*this, ConstraintKind::PackElementOf, first, second,
9031+
getConstraintLocator(locator)));
90469032

90479033
return SolutionKind::Solved;
9034+
};
9035+
9036+
// If neither side is fully resolved yet, there is nothing we can do.
9037+
if (elementType->hasTypeVariable() && patternType->hasTypeVariable())
9038+
return formUnsolved();
9039+
9040+
if (shouldAttemptFixes()) {
9041+
if (elementType->isPlaceholder() || patternType->isPlaceholder())
9042+
return SolutionKind::Solved;
90489043
}
90499044

9050-
// FIXME: I'm not sure this is actually necessary; I may only be seeing
9051-
// this because of something I've screwed up in element generic
9052-
// environments.
9053-
elementType = lookThroughSingletonPackExpansion(elementType);
9045+
// Let's try to resolve element type based on the pattern type.
9046+
if (!patternType->hasTypeVariable()) {
9047+
auto *loc = getConstraintLocator(locator);
9048+
auto shapeClass = patternType->getReducedShape();
9049+
patternType = patternType->mapTypeOutOfContext();
9050+
auto *elementEnv = getPackElementEnvironment(loc, shapeClass);
90549051

9055-
// This constraint only exists to vend bindings.
9056-
auto *packEnv = DC->getGenericEnvironmentOfContext();
9052+
// Without an opened element environment, we cannot derive the
9053+
// element binding.
9054+
if (!elementEnv) {
9055+
if (!shouldAttemptFixes())
9056+
return SolutionKind::Error;
90579057

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

9065-
// Pack expansions can have concrete pattern types. In this case, the pack
9066-
// type and element type will be equal.
9067-
if (packType->isEqual(elementType)) {
9068-
return SolutionKind::Solved;
9069-
}
9064+
// Only other posibility is that there is a shape mismatch between
9065+
// elements of the pack expansion pattern which is detected separately.
90709066

9071-
if (shouldAttemptFixes()) {
9072-
auto *loc = getConstraintLocator(locator);
9073-
if (elementType->isPlaceholder() ||
9074-
!recordFix(AllowInvalidPackElement::create(*this, packType, loc)))
9067+
recordAnyTypeVarAsPotentialHole(elementType);
90759068
return SolutionKind::Solved;
9069+
}
9070+
9071+
auto expectedElementTy =
9072+
elementEnv->mapPackTypeIntoElementContext(patternType);
9073+
assert(!expectedElementTy->is<PackType>());
9074+
9075+
addConstraint(ConstraintKind::Equal, elementType, expectedElementTy,
9076+
locator);
9077+
return SolutionKind::Solved;
90769078
}
90779079

9078-
return SolutionKind::Error;
9080+
// Otherwise we are inferred or checking pattern type.
9081+
9082+
auto *packEnv = DC->getGenericEnvironmentOfContext();
9083+
9084+
// Map element archetypes to the pack context to check for equality.
9085+
if (elementType->hasElementArchetype())
9086+
elementType = packEnv->mapElementTypeIntoPackContext(elementType);
9087+
9088+
addConstraint(ConstraintKind::Equal, elementType, patternType, locator);
9089+
return SolutionKind::Solved;
90799090
}
90809091

90819092
static bool isForKeyPathSubscript(ConstraintSystem &cs,

0 commit comments

Comments
 (0)