Skip to content

Commit f95109d

Browse files
committed
Sema: Restore old behavior of generic parameters with associated type inference
This effectively reverts d0bd026, so 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 4fc2fe9 commit f95109d

5 files changed

+44
-29
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

test/decl/protocol/req/associated_type_inference_fixed_type_experimental_inference.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ do {
214214
// CHECK-NEXT: }
215215
struct Conformer1: P17a {} // expected-error {{type 'Conformer1' does not conform to protocol 'P17a'}}
216216
// CHECK-LABEL: Abstract type witness system for conformance of Conformer2<A> to P17b: {
217-
// CHECK-NEXT: A => A (preferred), [[EQUIV_CLASS:0x[0-9a-f]+]]
217+
// CHECK-NEXT: A => (unresolved), [[EQUIV_CLASS:0x[0-9a-f]+]]
218218
// CHECK-NEXT: B => (unresolved)
219219
// CHECK-NEXT: }
220220
struct Conformer2<A>: P17b {} // expected-error {{type 'Conformer2<A>' does not conform to protocol 'P17b'}}
@@ -223,7 +223,7 @@ do {
223223
// CHECK-NEXT: }
224224
struct Conformer3: P17c {}
225225
// CHECK-LABEL: Abstract type witness system for conformance of Conformer4<A> to P17d: {
226-
// CHECK-NEXT: A => A (preferred), [[EQUIV_CLASS:0x[0-9a-f]+]]
226+
// CHECK-NEXT: A => Int (preferred), [[EQUIV_CLASS:0x[0-9a-f]+]]
227227
// CHECK-NEXT: B => Int (preferred), [[EQUIV_CLASS:0x[0-9a-f]+]]
228228
// CHECK-NEXT: }
229229
struct Conformer4<A>: P17d {}
@@ -645,7 +645,7 @@ protocol P37b {
645645
}
646646
do {
647647
// CHECK-LABEL: Abstract type witness system for conformance of Conformer1<C> to P37b: {
648-
// CHECK-NEXT: C => C (preferred),
648+
// CHECK-NEXT: C => Self.B.A (preferred),
649649
// CHECK-NEXT: }
650650
struct Conformer1<C>: P37b {
651651
struct Inner: P37a { typealias A = C }

test/decl/protocol/req/associated_type_inference_stdlib_3.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
1+
// RUN: not %target-typecheck-verify-swift -enable-experimental-associated-type-inference
22
// RUN: not %target-typecheck-verify-swift -disable-experimental-associated-type-inference
33

4+
// FIXME: Get this passing with -enable-experimental-associated-type-inference again.
5+
46
struct FooIterator<T: Sequence>: IteratorProtocol {
57
typealias Element = T.Element
68

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)