Skip to content

Commit 4921e06

Browse files
committed
GSB: Fix over-eager caching in EquivalenceClass::lookupNestedType()
We would invalidate the cache if the superclass changed, but not the concrete type. Let's do the same with the concrete type. This fixes one small part of rdar://problem/75656022.
1 parent 412ceef commit 4921e06

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ class GenericSignatureBuilder {
270270
struct CachedNestedType {
271271
unsigned numConformancesPresent;
272272
CanType superclassPresent;
273+
CanType concreteTypePresent;
273274
llvm::TinyPtrVector<TypeDecl *> types;
274275
};
275276

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2124,7 +2124,9 @@ TypeDecl *EquivalenceClass::lookupNestedType(
21242124
if (cached != nestedTypeNameCache.end() &&
21252125
cached->second.numConformancesPresent == conformsTo.size() &&
21262126
(!superclass ||
2127-
cached->second.superclassPresent == superclass->getCanonicalType())) {
2127+
cached->second.superclassPresent == superclass->getCanonicalType()) &&
2128+
(!concreteType ||
2129+
cached->second.concreteTypePresent == concreteType->getCanonicalType())) {
21282130
++NumNestedTypeCacheHits;
21292131
return populateResult(cached->second);
21302132
}
@@ -2176,6 +2178,8 @@ TypeDecl *EquivalenceClass::lookupNestedType(
21762178
entry.numConformancesPresent = conformsTo.size();
21772179
entry.superclassPresent =
21782180
superclass ? superclass->getCanonicalType() : CanType();
2181+
entry.concreteTypePresent =
2182+
concreteType ? concreteType->getCanonicalType() : CanType();
21792183
if (bestAssocType) {
21802184
entry.types.push_back(bestAssocType);
21812185
entry.types.insert(entry.types.end(),

test/Generics/rdar75656022.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
3+
4+
protocol P1 {
5+
associatedtype T
6+
}
7+
8+
protocol P2 {
9+
associatedtype T : P1
10+
}
11+
12+
struct S1<A, B, C> : P2
13+
where A : P1, C : P2, B == A.T.T, C.T == A.T {
14+
typealias T = C.T
15+
}
16+
17+
struct S2<D : P1> : P2 {
18+
typealias T = D
19+
}
20+
21+
// Make sure that we can resolve the nested type A.T
22+
// in the same-type requirement 'A.T == B.T'.
23+
//
24+
// A is concrete, and S1<C, E, S2<D>>.T resolves to
25+
// S2<D>.T, which is D. The typealias S1.T has a
26+
// structural type 'C.T'; since C is concrete, we
27+
// have to handle the case of an unresolved member
28+
// type with a concrete base.
29+
struct UnresolvedWithConcreteBase<A, B> {
30+
// CHECK-LABEL: Generic signature: <A, B, C, D, E where A == S1<C, E, S2<D>>, B : P2, C : P1, D == B.T, E == D.T, B.T == C.T>
31+
init<C, D, E>(_: C)
32+
where A == S1<C, E, S2<D>>,
33+
B : P2,
34+
A.T == B.T,
35+
C : P1,
36+
D == C.T,
37+
E == D.T { }
38+
}

0 commit comments

Comments
 (0)