Skip to content

Commit fe7631c

Browse files
committed
Sema: Change associated type inference handling of generic parameters
Instead of eagerly binding a generic parameter to an abstract type witness, introduce them as disjunctions. Fixes rdar://problem/122587432.
1 parent 23ef893 commit fe7631c

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,6 @@ class AssociatedTypeInference {
980980

981981
/// Infer associated type witnesses for the given associated type.
982982
InferredAssociatedTypesByWitnesses inferTypeWitnessesViaAssociatedType(
983-
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
984983
AssociatedTypeDecl *assocType);
985984

986985
/// Infer associated type witnesses for all relevant value requirements.
@@ -1679,8 +1678,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
16791678
if (assocTypes.count(assocType) == 0)
16801679
continue;
16811680

1682-
auto reqInferred = inferTypeWitnessesViaAssociatedType(assocTypes,
1683-
assocType);
1681+
auto reqInferred = inferTypeWitnessesViaAssociatedType(assocType);
16841682
if (!reqInferred.empty())
16851683
result.push_back({req, std::move(reqInferred)});
16861684

@@ -1828,10 +1826,12 @@ static Type removeSelfParam(ValueDecl *value, Type type) {
18281826

18291827
InferredAssociatedTypesByWitnesses
18301828
AssociatedTypeInference::inferTypeWitnessesViaAssociatedType(
1831-
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
18321829
AssociatedTypeDecl *assocType) {
18331830
InferredAssociatedTypesByWitnesses result;
18341831

1832+
LLVM_DEBUG(llvm::dbgs() << "Considering associated type:\n";
1833+
assocType->dump(llvm::dbgs()));
1834+
18351835
// Check if this associated type is actually fixed to a fully concrete type by
18361836
// a same-type requirement in a protocol that our conforming type conforms to.
18371837
//
@@ -1856,6 +1856,34 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType(
18561856
}
18571857
}
18581858

1859+
// Look for a generic parameter with the same name as this associated type.
1860+
if (ctx.LangOpts.EnableExperimentalAssociatedTypeInference) {
1861+
// Ignore the generic parameters for AsyncIteratorProtocol.Failure and
1862+
// AsyncSequence.Failure.
1863+
if (!isAsyncIteratorProtocolFailure(assocType)) {
1864+
if (auto genericSig = dc->getGenericSignatureOfContext()) {
1865+
for (auto *gp : genericSig.getInnermostGenericParams()) {
1866+
// Packs cannot witness associated type requirements.
1867+
if (gp->isParameterPack())
1868+
continue;
1869+
1870+
if (gp->getName() == assocType->getName()) {
1871+
auto witnessType = dc->mapTypeIntoContext(gp);
1872+
1873+
// Add this result.
1874+
InferredAssociatedTypesByWitness inferred;
1875+
inferred.Witness = gp->getDecl();
1876+
inferred.Inferred.push_back({assocType, witnessType});
1877+
result.push_back(std::move(inferred));
1878+
1879+
LLVM_DEBUG(llvm::dbgs() << "Candidate generic parameter:\n";
1880+
gp->dump(llvm::dbgs()));
1881+
}
1882+
}
1883+
}
1884+
}
1885+
}
1886+
18591887
// Form the default name _Default_Foo.
18601888
DeclNameRef defaultName;
18611889
{
@@ -2440,29 +2468,6 @@ AssociatedTypeInference::computeAbstractTypeWitness(
24402468
void AssociatedTypeInference::collectAbstractTypeWitnesses(
24412469
TypeWitnessSystem &system,
24422470
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes) const {
2443-
// Look for suitably-named generic parameters first, before we go digging
2444-
// through same-type requirements of protocols.
2445-
if (auto genericSig = dc->getGenericSignatureOfContext()) {
2446-
for (auto *const assocType : unresolvedAssocTypes) {
2447-
// Ignore the generic parameters for AsyncIteratorProtocol.Failure and
2448-
// AsyncSequence.Failure.
2449-
if (isAsyncIteratorProtocolFailure(assocType))
2450-
continue;
2451-
2452-
for (auto *gp : genericSig.getInnermostGenericParams()) {
2453-
// Packs cannot witness associated type requirements.
2454-
if (gp->isParameterPack())
2455-
continue;
2456-
2457-
if (gp->getName() == assocType->getName()) {
2458-
system.addTypeWitness(assocType->getName(),
2459-
dc->mapTypeIntoContext(gp),
2460-
/*preferred=*/true);
2461-
}
2462-
}
2463-
}
2464-
}
2465-
24662471
auto considerProtocolRequirements = [&](ProtocolDecl *conformedProto) {
24672472
// FIXME: The RequirementMachine will assert on re-entrant construction.
24682473
// We should find a more principled way of breaking this cycle.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
2+
// RUN: %target-typecheck-verify-swift -disable-experimental-associated-type-inference
3+
4+
public struct S<Element: Hashable> {
5+
public typealias A = [Element: Int]
6+
}
7+
8+
extension S: Sequence {
9+
public func makeIterator() -> A.Iterator {
10+
fatalError()
11+
}
12+
}
13+
14+
let x: (key: String, value: Int).Type = S<String>.Element.self

0 commit comments

Comments
 (0)