Skip to content

Commit f4d53a3

Browse files
committed
[CSBindings] Instead of breaking a PackElementOf constraint down into Bind
constraints, vend potential bindings through PotentialBindings::infer. This allows for bidirectional binding inference from the pack type to the element type and vice versa.
1 parent 2e1c47a commit f4d53a3

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616
#include "swift/Sema/CSBindings.h"
1717
#include "TypeChecker.h"
18+
#include "swift/AST/GenericEnvironment.h"
1819
#include "swift/Sema/ConstraintGraph.h"
1920
#include "swift/Sema/ConstraintSystem.h"
2021
#include "llvm/ADT/SetVector.h"
@@ -1404,12 +1405,51 @@ void PotentialBindings::infer(Constraint *constraint) {
14041405
case ConstraintKind::SyntacticElement:
14051406
case ConstraintKind::Conjunction:
14061407
case ConstraintKind::BindTupleOfFunctionParams:
1407-
case ConstraintKind::PackElementOf:
14081408
case ConstraintKind::ShapeOf:
14091409
case ConstraintKind::ExplicitGenericArguments:
14101410
// Constraints from which we can't do anything.
14111411
break;
14121412

1413+
case ConstraintKind::PackElementOf: {
1414+
auto elementType = CS.simplifyType(constraint->getFirstType());
1415+
auto packType = CS.simplifyType(constraint->getSecondType());
1416+
1417+
auto *loc = constraint->getLocator();
1418+
auto openedElement =
1419+
loc->getLastElementAs<LocatorPathElt::OpenedPackElement>();
1420+
1421+
if (elementType->isTypeVariableOrMember() && packType->isTypeVariableOrMember())
1422+
break;
1423+
1424+
auto *elementVar = elementType->getAs<TypeVariableType>();
1425+
auto *packVar = packType->getAs<TypeVariableType>();
1426+
1427+
if (elementVar == TypeVar && !packVar) {
1428+
// Produce a potential binding to the opened element archetype corresponding
1429+
// to the pack type.
1430+
packType = packType->mapTypeOutOfContext();
1431+
if (auto *expansion = packType->getAs<PackExpansionType>())
1432+
packType = expansion->getPatternType();
1433+
1434+
auto *elementEnv = openedElement->getGenericEnvironment();
1435+
auto elementType = elementEnv->mapPackTypeIntoElementContext(packType);
1436+
addPotentialBinding({elementType, AllowedBindingKind::Exact, constraint});
1437+
1438+
break;
1439+
} else if (packVar == TypeVar && !elementVar) {
1440+
// Produce a potential binding to the pack archetype corresponding to
1441+
// the opened element type.
1442+
auto *packEnv = CS.DC->getGenericEnvironmentOfContext();
1443+
elementType = elementType->mapTypeOutOfContext();
1444+
auto patternType = packEnv->mapElementTypeIntoPackContext(elementType);
1445+
addPotentialBinding({patternType, AllowedBindingKind::Exact, constraint});
1446+
1447+
break;
1448+
}
1449+
1450+
break;
1451+
}
1452+
14131453
// For now let's avoid inferring protocol requirements from
14141454
// this constraint, but in the future we could do that to
14151455
// to filter bindings.

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2956,6 +2956,7 @@ namespace {
29562956
}
29572957

29582958
Type visitPackExpansionExpr(PackExpansionExpr *expr) {
2959+
auto *elementEnv = expr->getGenericEnvironment();
29592960
for (auto *binding : expr->getBindings()) {
29602961
auto type = visit(binding);
29612962
CS.setType(binding, type);
@@ -2967,8 +2968,10 @@ namespace {
29672968
TVO_CanBindToPack |
29682969
TVO_CanBindToHole);
29692970
auto elementResultType = CS.getType(expr->getPatternExpr());
2971+
auto *elementLoc = CS.getConstraintLocator(
2972+
expr, LocatorPathElt::OpenedPackElement(elementEnv));
29702973
CS.addConstraint(ConstraintKind::PackElementOf, elementResultType,
2971-
patternTy, CS.getConstraintLocator(expr));
2974+
patternTy, elementLoc);
29722975

29732976
auto *shapeLoc =
29742977
CS.getConstraintLocator(expr, ConstraintLocator::PackShape);

lib/Sema/CSSimplify.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8561,27 +8561,28 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
85618561
TypeMatchOptions flags,
85628562
ConstraintLocatorBuilder locator) {
85638563
auto elementType = simplifyType(first, flags);
8564-
auto *loc = getConstraintLocator(locator);
8564+
auto packType = simplifyType(second, flags);
85658565

8566-
if (elementType->hasTypeVariable()) {
8566+
if (elementType->hasTypeVariable() || packType->hasTypeVariable()) {
85678567
if (!flags.contains(TMF_GenerateConstraints))
85688568
return SolutionKind::Unsolved;
85698569

8570+
auto *loc = getConstraintLocator(locator);
85708571
addUnsolvedConstraint(
85718572
Constraint::create(*this, ConstraintKind::PackElementOf,
85728573
first, second, loc));
85738574

85748575
return SolutionKind::Solved;
85758576
}
85768577

8577-
// Replace opened element archetypes with pack archetypes
8578-
// for the resulting type of the pack expansion.
8579-
auto *environment = DC->getGenericEnvironmentOfContext();
8580-
auto patternType = environment->mapElementTypeIntoPackContext(
8581-
elementType->mapTypeOutOfContext());
8582-
addConstraint(ConstraintKind::Bind, second, patternType, locator);
8583-
8584-
return SolutionKind::Solved;
8578+
// This constraint only exists to vend bindings.
8579+
auto *packEnv = DC->getGenericEnvironmentOfContext();
8580+
if (packType->isEqual(packEnv->mapElementTypeIntoPackContext
8581+
(elementType->mapTypeOutOfContext()))) {
8582+
return SolutionKind::Solved;
8583+
} else {
8584+
return SolutionKind::Error;
8585+
}
85858586
}
85868587

85878588
static bool isForKeyPathSubscript(ConstraintSystem &cs,

0 commit comments

Comments
 (0)