Skip to content

Commit 2d5b04e

Browse files
committed
AST: Don't canonicalize GenericFunctionTypes in TypeBase::getASTContext()
A TypeBase stores either an ASTContext if its canonical, or its canonical type if it is not. getASTContext() will then canonicalize the type if its not canonical. While this is very clever, in the case of a GenericFunctionType, it triggers the rather expensive creation of a GenericSignatureBuilder. Avoid this by special-casing GenericFunctionType here and getting the ASTContext from a structural sub-component that is known to exist instead.
1 parent 398d07f commit 2d5b04e

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

include/swift/AST/Types.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -492,13 +492,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
492492
TypeBase *getWithoutSyntaxSugar();
493493

494494
/// getASTContext - Return the ASTContext that this type belongs to.
495-
ASTContext &getASTContext() {
496-
// If this type is canonical, it has the ASTContext in it.
497-
if (isCanonical())
498-
return *const_cast<ASTContext*>(Context);
499-
// If not, canonicalize it to get the Context.
500-
return *const_cast<ASTContext*>(getCanonicalType()->Context);
501-
}
495+
ASTContext &getASTContext();
502496

503497
/// isEqual - Return true if these two types are equal, ignoring sugar.
504498
///
@@ -5994,6 +5988,22 @@ class PlaceholderType : public TypeBase {
59945988
};
59955989
DEFINE_EMPTY_CAN_TYPE_WRAPPER(PlaceholderType, Type)
59965990

5991+
/// getASTContext - Return the ASTContext that this type belongs to.
5992+
inline ASTContext &TypeBase::getASTContext() {
5993+
// If this type is canonical, it has the ASTContext in it.
5994+
if (isCanonical())
5995+
return *const_cast<ASTContext*>(Context);
5996+
5997+
// getCanonicalType() on GenericFunctionType is very expensive;
5998+
// instead we can more easily fish the ASTContext out of any
5999+
// structural sub-component.
6000+
if (auto *genericFnType = dyn_cast<GenericFunctionType>(this))
6001+
return genericFnType->getGenericParams()[0]->getASTContext();
6002+
6003+
// If not, canonicalize it to get the Context.
6004+
return *const_cast<ASTContext*>(getCanonicalType()->Context);
6005+
}
6006+
59976007
inline bool TypeBase::isTypeVariableOrMember() {
59986008
if (is<TypeVariableType>())
59996009
return true;

0 commit comments

Comments
 (0)