Skip to content

Commit ee2d67f

Browse files
committed
Sema: Restore old behavior of generic parameters with associated type inference
We now look for abstract type witnesses before generic parameters. In particular, this means we again prefer the default type witness over a generic parameter if nothing else forces it to be a generic parameter: protocol P { associatedtype A = Int } struct S<T>: P {} // S.T is always Int Fixing this properly requires modeling generic parameter bindings as disjunctions, which is a more disruptive change than I want to take for now. Fixes rdar://problem/122587432.
1 parent c2057c3 commit ee2d67f

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,29 +2440,6 @@ AssociatedTypeInference::computeAbstractTypeWitness(
24402440
void AssociatedTypeInference::collectAbstractTypeWitnesses(
24412441
TypeWitnessSystem &system,
24422442
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-
24662443
auto considerProtocolRequirements = [&](ProtocolDecl *conformedProto) {
24672444
// FIXME: The RequirementMachine will assert on re-entrant construction.
24682445
// We should find a more principled way of breaking this cycle.
@@ -2515,7 +2492,28 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
25152492
system.addDefaultTypeWitness(typeWitness->getType(),
25162493
typeWitness->getDefaultedAssocType(),
25172494
preferred);
2495+
} else {
2496+
// As a last resort, look for a generic parameter that matches the name
2497+
// of the associated type.
2498+
if (auto genericSig = dc->getGenericSignatureOfContext()) {
2499+
// Ignore the generic parameters for AsyncIteratorProtocol.Failure and
2500+
// AsyncSequence.Failure.
2501+
if (!isAsyncIteratorProtocolFailure(assocType)) {
2502+
for (auto *gp : genericSig.getInnermostGenericParams()) {
2503+
// Packs cannot witness associated type requirements.
2504+
if (gp->isParameterPack())
2505+
continue;
2506+
2507+
if (gp->getName() == assocType->getName()) {
2508+
system.addTypeWitness(assocType->getName(),
2509+
dc->mapTypeIntoContext(gp),
2510+
/*preferred=*/true);
2511+
}
2512+
}
2513+
}
2514+
}
25182515
}
2516+
25192517
}
25202518
}
25212519

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
2-
// RUN: not %target-typecheck-verify-swift -disable-experimental-associated-type-inference
2+
// RUN: %target-typecheck-verify-swift -disable-experimental-associated-type-inference
33

44
protocol P {
55
associatedtype A = Int
66
}
77

88
struct S<A>: P {}
99

10-
let x: String.Type = S<String>.A.self
10+
// This is unfortunate but it is the behavior of Swift 5.10.
11+
let x: Int.Type = S<String>.A.self
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)