Skip to content

Commit 5a5c904

Browse files
authored
Merge pull request #60205 from amritpan/add-atom-kind
[ConstraintSystem] Specify atom and collection literal kinds for type variable attributes.
2 parents e7a4661 + 3ae85ab commit 5a5c904

File tree

2 files changed

+81
-15
lines changed

2 files changed

+81
-15
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,11 @@ class BindingSet {
470470
return Info.AssociatedCodeCompletionToken;
471471
}
472472

473-
LiteralBindingKind getLiteralKind() const;
473+
void forEachLiteralRequirement(
474+
llvm::function_ref<void(KnownProtocolKind)> callback) const;
475+
476+
/// Return a literal requirement that has the most impact on the binding score.
477+
LiteralBindingKind getLiteralForScore() const;
474478

475479
/// Check if this binding is favored over a disjunction e.g.
476480
/// if it has only concrete types or would resolve a closure.

lib/Sema/CSBindings.cpp

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ BindingSet::BindingScore BindingSet::formBindingScore(const BindingSet &b) {
741741
return std::make_tuple(b.isHole(), numNonDefaultableBindings == 0,
742742
b.isDelayed(), b.isSubtypeOfExistentialType(),
743743
b.involvesTypeVariables(),
744-
static_cast<unsigned char>(b.getLiteralKind()),
744+
static_cast<unsigned char>(b.getLiteralForScore()),
745745
-numNonDefaultableBindings);
746746
}
747747

@@ -1577,18 +1577,26 @@ void PotentialBindings::retract(Constraint *constraint) {
15771577
EquivalentTo.remove_if(hasMatchingSource);
15781578
}
15791579

1580-
LiteralBindingKind BindingSet::getLiteralKind() const {
1581-
LiteralBindingKind kind = LiteralBindingKind::None;
1582-
1580+
void BindingSet::forEachLiteralRequirement(
1581+
llvm::function_ref<void(KnownProtocolKind)> callback) const {
15831582
for (const auto &literal : Literals) {
15841583
auto *protocol = literal.first;
15851584
const auto &info = literal.second;
15861585

15871586
// Only uncovered defaultable literal protocols participate.
15881587
if (!info.viableAsBinding())
15891588
continue;
1589+
1590+
if (auto protocolKind = protocol->getKnownProtocolKind())
1591+
callback(*protocolKind);
1592+
}
1593+
}
15901594

1591-
switch (*protocol->getKnownProtocolKind()) {
1595+
LiteralBindingKind BindingSet::getLiteralForScore() const {
1596+
LiteralBindingKind kind = LiteralBindingKind::None;
1597+
1598+
forEachLiteralRequirement([&](KnownProtocolKind protocolKind) {
1599+
switch (protocolKind) {
15921600
case KnownProtocolKind::ExpressibleByDictionaryLiteral:
15931601
case KnownProtocolKind::ExpressibleByArrayLiteral:
15941602
case KnownProtocolKind::ExpressibleByStringInterpolation:
@@ -1604,8 +1612,7 @@ LiteralBindingKind BindingSet::getLiteralKind() const {
16041612
kind = LiteralBindingKind::Atom;
16051613
break;
16061614
}
1607-
}
1608-
1615+
});
16091616
return kind;
16101617
}
16111618

@@ -1615,6 +1622,39 @@ unsigned BindingSet::getNumViableLiteralBindings() const {
16151622
});
16161623
}
16171624

1625+
/// Return string for atomic literal kinds (integer, string, & boolean) for
1626+
/// printing in debug output.
1627+
static std::string getAtomLiteralAsString(ExprKind EK) {
1628+
#define ENTRY(Kind, String) \
1629+
case ExprKind::Kind: \
1630+
return String
1631+
switch (EK) {
1632+
ENTRY(IntegerLiteral, "integer");
1633+
ENTRY(StringLiteral, "string");
1634+
ENTRY(BooleanLiteral, "boolean");
1635+
ENTRY(NilLiteral, "nil");
1636+
default:
1637+
return "";
1638+
}
1639+
#undef ENTRY
1640+
}
1641+
1642+
/// Return string for collection literal kinds (interpolated string, array,
1643+
/// dictionary) for printing in debug output.
1644+
static std::string getCollectionLiteralAsString(KnownProtocolKind KPK) {
1645+
#define ENTRY(Kind, String) \
1646+
case KnownProtocolKind::Kind: \
1647+
return String
1648+
switch (KPK) {
1649+
ENTRY(ExpressibleByDictionaryLiteral, "dictionary");
1650+
ENTRY(ExpressibleByArrayLiteral, "array");
1651+
ENTRY(ExpressibleByStringInterpolation, "interpolated string");
1652+
default:
1653+
return "";
1654+
}
1655+
#undef ENTRY
1656+
}
1657+
16181658
void BindingSet::dump(TypeVariableType *typeVar, llvm::raw_ostream &out,
16191659
unsigned indent) const {
16201660
out.indent(indent);
@@ -1639,17 +1679,39 @@ void BindingSet::dump(llvm::raw_ostream &out, unsigned indent) const {
16391679
attributes.push_back("delayed");
16401680
if (isSubtypeOfExistentialType())
16411681
attributes.push_back("subtype_of_existential");
1642-
auto literalKind = getLiteralKind();
1643-
if (literalKind != LiteralBindingKind::None) {
1644-
auto literalAttrStr = ("[literal: " + getLiteralBindingKind(literalKind)
1645-
+ "]").str();
1646-
attributes.push_back(literalAttrStr);
1647-
}
16481682
if (!attributes.empty()) {
16491683
out << "[attributes: ";
16501684
interleave(attributes, out, ", ");
1651-
out << "] ";
16521685
}
1686+
1687+
auto literalKind = getLiteralForScore();
1688+
if (literalKind != LiteralBindingKind::None) {
1689+
out << ", [literal: ";
1690+
switch (literalKind) {
1691+
case LiteralBindingKind::Atom: {
1692+
if (auto atomKind = TypeVar->getImpl().getAtomicLiteralKind()) {
1693+
out << getAtomLiteralAsString(*atomKind);
1694+
}
1695+
break;
1696+
}
1697+
case LiteralBindingKind::Collection: {
1698+
std::vector<std::string> collectionLiterals;
1699+
forEachLiteralRequirement([&](KnownProtocolKind protocolKind) {
1700+
collectionLiterals.push_back(
1701+
getCollectionLiteralAsString(protocolKind));
1702+
});
1703+
interleave(collectionLiterals, out, ", ");
1704+
break;
1705+
}
1706+
case LiteralBindingKind::Float:
1707+
case LiteralBindingKind::None:
1708+
out << getLiteralBindingKind(literalKind).str();
1709+
break;
1710+
}
1711+
out << "]";
1712+
}
1713+
out << "] ";
1714+
16531715
if (involvesTypeVariables()) {
16541716
out << "[involves_type_vars: ";
16551717
interleave(AdjacentVars,

0 commit comments

Comments
 (0)