Skip to content

Commit 9ca1157

Browse files
committed
Add cache for USRBasedTypeContext::typeRelation
This brings the time taken for the cached completion: ``` import SwiftUI Table(#^CC^# ``` down from ~400ms to ~190ms.
1 parent 1a62f36 commit 9ca1157

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

include/swift/IDE/CodeCompletionResultType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ class USRBasedTypeContext {
207207
/// allocated.
208208
const USRBasedTypeArena &Arena;
209209

210+
/// A cached set of type relations for this given type context.
211+
mutable llvm::DenseMap<const USRBasedType *, CodeCompletionResultTypeRelation>
212+
CachedTypeRelations;
213+
210214
SmallVector<ContextualType, 4> ContextualTypes;
211215

212216
/// See \c ExpectedTypeContext::ExpectedAttributeKinds.

lib/IDE/CodeCompletionResultType.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,37 @@ USRBasedTypeContext::USRBasedTypeContext(const ExpectedTypeContext *TypeContext,
8888

8989
TypeRelation
9090
USRBasedTypeContext::typeRelation(const USRBasedType *ResultType) const {
91-
if (ExpectedCustomAttributeKinds) {
92-
return ResultType->getCustomAttributeKinds() & ExpectedCustomAttributeKinds
93-
? TypeRelation::Convertible
94-
: TypeRelation::Unrelated;
95-
}
96-
const USRBasedType *VoidType = Arena.getVoidType();
97-
if (ResultType == VoidType) {
98-
// Void is not convertible to anything and we don't report Void <-> Void
99-
// identical matches (see USRBasedType::typeRelation). So we don't have to
100-
// check anything if the result returns Void.
101-
return TypeRelation::Unknown;
102-
}
91+
auto compute = [&]() -> TypeRelation {
92+
if (ExpectedCustomAttributeKinds) {
93+
return ResultType->getCustomAttributeKinds() &
94+
ExpectedCustomAttributeKinds
95+
? TypeRelation::Convertible
96+
: TypeRelation::Unrelated;
97+
}
98+
const USRBasedType *VoidType = Arena.getVoidType();
99+
if (ResultType == VoidType) {
100+
// Void is not convertible to anything and we don't report Void <-> Void
101+
// identical matches (see USRBasedType::typeRelation). So we don't have to
102+
// check anything if the result returns Void.
103+
return TypeRelation::Unknown;
104+
}
103105

104-
TypeRelation Res = TypeRelation::Unknown;
105-
for (auto &ContextualType : ContextualTypes) {
106-
Res = std::max(Res, ContextualType.typeRelation(ResultType, VoidType));
107-
if (Res == TypeRelation::MAX_VALUE) {
108-
return Res; // We can't improve further
106+
TypeRelation Res = TypeRelation::Unknown;
107+
for (auto &ContextualType : ContextualTypes) {
108+
Res = std::max(Res, ContextualType.typeRelation(ResultType, VoidType));
109+
if (Res == TypeRelation::MAX_VALUE) {
110+
return Res; // We can't improve further
111+
}
109112
}
110-
}
111-
return Res;
113+
return Res;
114+
};
115+
auto iter = CachedTypeRelations.find(ResultType);
116+
if (iter != CachedTypeRelations.end())
117+
return iter->second;
118+
119+
auto relation = compute();
120+
CachedTypeRelations.insert({ResultType, relation});
121+
return relation;
112122
}
113123

114124
// MARK: - USRBasedTypeArena

0 commit comments

Comments
 (0)