Skip to content

Commit dd36c5b

Browse files
committed
Sema: Comments comments comments
1 parent c62639f commit dd36c5b

File tree

1 file changed

+65
-47
lines changed

1 file changed

+65
-47
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,8 +1228,7 @@ struct TypeReprCycleCheckWalker : ASTWalker {
12281228
bool checkForPotentialCycle(ValueDecl *witness) {
12291229
// Don't do this for protocol extension members, because we have a
12301230
// mini "solver" that avoids similar issues instead.
1231-
if (witness->getDeclContext()->getSelfProtocolDecl() != nullptr)
1232-
return false;
1231+
assert(!witness->getDeclContext()->getExtendedProtocolDecl());
12331232

12341233
// If we already have an interface type, don't bother trying to
12351234
// avoid a cycle.
@@ -1383,12 +1382,9 @@ enum class InferenceCandidateKind {
13831382
static InferenceCandidateKind checkInferenceCandidate(
13841383
std::pair<AssociatedTypeDecl *, Type> *result,
13851384
NormalProtocolConformance *conformance,
1386-
ValueDecl *witness) {
1387-
auto witnessContext = witness->getDeclContext();
1388-
auto &ctx = witnessContext->getASTContext();
1389-
1390-
assert(witnessContext->getExtendedProtocolDecl());
1391-
auto selfTy = witnessContext->getSelfInterfaceType();
1385+
DeclContext *witnessDC,
1386+
Type selfTy) {
1387+
auto &ctx = selfTy->getASTContext();
13921388

13931389
auto isTautological = [&](Type t) -> bool {
13941390
auto dmt = t->getAs<DependentMemberType>();
@@ -1416,17 +1412,16 @@ static InferenceCandidateKind checkInferenceCandidate(
14161412
return true;
14171413
};
14181414

1415+
// Self.X == Self.X doesn't give us any new information, nor does it
1416+
// immediately fail.
14191417
if (isTautological(result->second)) {
14201418
auto *dmt = result->second->castTo<DependentMemberType>();
14211419

1422-
// If this associated type is same-typed to another associated type
1423-
// on `Self`, then it may still be an interesting candidate if we find
1424-
// an answer for that other type.
1425-
auto selfTy = witnessContext->getSelfInterfaceType();
1426-
auto selfAssocTy = DependentMemberType::get(selfTy,
1427-
dmt->getAssocType());
1428-
for (auto &reqt : witnessContext->getGenericSignatureOfContext()
1429-
.getRequirements()) {
1420+
auto selfAssocTy = DependentMemberType::get(selfTy, dmt->getAssocType());
1421+
1422+
// If we have a same-type requirement `Self.X == Self.Y`,
1423+
// introduce a binding `Self.X := Self.Y`.
1424+
for (auto &reqt : witnessDC->getGenericSignatureOfContext().getRequirements()) {
14301425
switch (reqt.getKind()) {
14311426
case RequirementKind::SameShape:
14321427
llvm_unreachable("Same-shape requirement not supported here");
@@ -1460,8 +1455,6 @@ static InferenceCandidateKind checkInferenceCandidate(
14601455

14611456
}
14621457

1463-
// We may be able to infer one associated type from the
1464-
// other.
14651458
result->second = result->second.transform([&](Type t) -> Type{
14661459
if (t->isEqual(dmt))
14671460
return otherDMT;
@@ -1479,6 +1472,8 @@ static InferenceCandidateKind checkInferenceCandidate(
14791472
return InferenceCandidateKind::Tautological;
14801473
}
14811474

1475+
// If we have something like `Self.X := G<Self.X>` on the other hand,
1476+
// the binding can never be satisfied.
14821477
if (result->second.findIf(isTautological))
14831478
return InferenceCandidateKind::Infinite;
14841479

@@ -1537,6 +1532,10 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15371532
LLVM_DEBUG(llvm::dbgs() << "Inferring associated types from decl:\n";
15381533
witness->dump(llvm::dbgs()));
15391534

1535+
// This is the protocol `Self` type if the witness is declared in a protocol
1536+
// extension, or nullptr.
1537+
Type selfTy;
1538+
15401539
// If the potential witness came from an extension, and our `Self`
15411540
// type can't use it regardless of what associated types we end up
15421541
// inferring, skip the witness.
@@ -1545,18 +1544,28 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15451544
LLVM_DEBUG(llvm::dbgs() << "Extension not usable for inference\n");
15461545
continue;
15471546
}
1547+
1548+
if (auto *proto = dyn_cast<ProtocolDecl>(extension->getExtendedNominal()))
1549+
selfTy = proto->getSelfInterfaceType();
15481550
}
15491551

1550-
if (cycleCheck.checkForPotentialCycle(witness)) {
1551-
LLVM_DEBUG(llvm::dbgs() << "Skipping witness to avoid request cycle\n");
1552+
if (!selfTy) {
1553+
if (cycleCheck.checkForPotentialCycle(witness)) {
1554+
LLVM_DEBUG(llvm::dbgs() << "Skipping witness to avoid request cycle\n");
15521555

1553-
// We must consider the possibility that none of the witnesses for this
1554-
// requirement can be chosen.
1555-
hadTautologicalWitness = true;
1556-
continue;
1556+
// We must consider the possibility that none of the witnesses for this
1557+
// requirement can be chosen.
1558+
hadTautologicalWitness = true;
1559+
continue;
1560+
}
15571561
}
15581562

1559-
// Try to resolve the type witness via this value witness.
1563+
// Match the type of the requirement against the type of the witness to
1564+
// produce a list of bindings. The left-hand side of each binding is an
1565+
// associated type of our protocol, and the right-hand side is either
1566+
// a concrete type (possibly containing archetypes of the conforming type)
1567+
// or a type parameter rooted in the protocol 'Self' type, representing
1568+
// an unresolved type witness.
15601569
auto witnessResult = getPotentialTypeWitnessesByMatchingTypes(req, witness);
15611570

15621571
// Filter out duplicated inferred types as well as inferred types
@@ -1574,9 +1583,10 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15741583
<< " can infer to:\n";
15751584
result.second->dump(llvm::dbgs()));
15761585

1577-
bool fromProtocolExtension =
1578-
witness->getDeclContext()->getExtendedProtocolDecl();
1579-
assert(!result.second->hasTypeParameter() || fromProtocolExtension);
1586+
assert(!result.second->hasTypeParameter() || selfTy &&
1587+
"We should only see unresolved type witnesses on the "
1588+
"right-hand side of a binding when the value witness came from a "
1589+
"protocol extension");
15801590

15811591
// Filter out errors.
15821592
if (result.second->hasError()) {
@@ -1595,42 +1605,48 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15951605
REJECT;
15961606
}
15971607

1598-
if (fromProtocolExtension) {
1599-
// Filter out circular possibilities, e.g. that
1600-
// AssocType == Self.AssocType or
1601-
// AssocType == Foo<Self.AssocType>.
1602-
switch (checkInferenceCandidate(&result, conformance, witness)) {
1608+
// The type of a potential value witness in a protocol extensions may
1609+
// itself involve unresolved type witnesses.
1610+
if (selfTy) {
1611+
// Handle Self.X := Self.X and Self.X := G<Self.X>.
1612+
switch (checkInferenceCandidate(&result, conformance,
1613+
witness->getDeclContext(), selfTy)) {
16031614
case InferenceCandidateKind::Good:
1604-
// Continued below.
1615+
// The "good" case is something like `Self.X := Self.Y`.
16051616
break;
16061617

16071618
case InferenceCandidateKind::Tautological: {
16081619
LLVM_DEBUG(llvm::dbgs() << "-- tautological\n");
1620+
// A tautology is the `Self.X := Self.X` case.
1621+
//
16091622
// Skip this binding because it is immediately satisfied.
16101623
REJECT;
16111624
}
16121625

16131626
case InferenceCandidateKind::Infinite: {
16141627
LLVM_DEBUG(llvm::dbgs() << "-- infinite\n");
1628+
// The infinite case is `Self.X := G<Self.X>`.
1629+
//
16151630
// Discard this witness altogether, because it has an unsatisfiable
16161631
// binding.
16171632
goto next_witness;
16181633
}
16191634
}
16201635
}
16211636

1622-
// Check that the binding doesn't contradict an explicitly-given type
1623-
// witness. If it does contradict, throw out the witness completely.
1637+
// Check that the binding doesn't contradict a type witness previously
1638+
// resolved via name lookup.
1639+
//
1640+
// If it does contradict, throw out the witness entirely.
16241641
if (!allUnresolved.count(result.first)) {
16251642
auto existingWitness =
16261643
conformance->getTypeWitness(result.first);
16271644
existingWitness = dc->mapTypeIntoContext(existingWitness);
16281645

1629-
// If the deduced type contains an irreducible
1630-
// DependentMemberType, that indicates a dependency
1631-
// on another associated type we haven't deduced,
1632-
// so we can't tell whether there's a contradiction
1633-
// yet.
1646+
// For now, only a fully-concrete binding can contradict an existing
1647+
// type witness.
1648+
//
1649+
// FIXME: Generate new constraints by matching the two types.
16341650
auto newWitness = result.second->getCanonicalType();
16351651
if (!newWitness->hasTypeParameter() &&
16361652
!newWitness->hasDependentMember() &&
@@ -1641,8 +1657,8 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
16411657
}
16421658
}
16431659

1644-
// Check that the type witness meets the requirements on the
1645-
// associated type.
1660+
// Check that the potential type witness satisfies the local requirements
1661+
// imposed upon the associated type.
16461662
if (auto failed =
16471663
checkTypeWitness(result.second, result.first, conformance)) {
16481664
witnessResult.NonViable.push_back(
@@ -1661,15 +1677,15 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
16611677
#undef REJECT
16621678

16631679
// If no viable or non-viable bindings remain, the witness does not
1664-
// inter anything new, nor contradict any existing bindings. We collapse
1665-
// all tautological witnesses into a single element of the disjunction.
1680+
// give us anything new or contradict any existing bindings. We collapse
1681+
// all tautological witnesses into a single disjunction term.
16661682
if (witnessResult.Inferred.empty() && witnessResult.NonViable.empty()) {
16671683
hadTautologicalWitness = true;
16681684
continue;
16691685
}
16701686

1671-
// If there were any non-viable inferred associated types, don't
1672-
// infer anything from this witness.
1687+
// If we had at least one non-viable binding, drop the viable bindings;
1688+
// we cannot infer anything from this witness.
16731689
if (!witnessResult.NonViable.empty())
16741690
witnessResult.Inferred.clear();
16751691

@@ -3627,6 +3643,8 @@ void AssociatedTypeInference::findSolutionsRec(
36273643

36283644
// If one has a type parameter remaining but the other does not,
36293645
// drop the one with the type parameter.
3646+
//
3647+
// FIXME: This is too ad-hoc. Generate new constraints instead.
36303648
if ((known->first->hasTypeParameter() ||
36313649
known->first->hasDependentMember())
36323650
!= (typeWitness.second->hasTypeParameter() ||

0 commit comments

Comments
 (0)