Skip to content

Commit f249db3

Browse files
committed
Use cached evaluator results when looking up function types.
Also improve the output for thrown error destinations in parsable modes.
1 parent 8df48e5 commit f249db3

File tree

7 files changed

+108
-31
lines changed

7 files changed

+108
-31
lines changed

include/swift/AST/Attr.h

+1
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,7 @@ class ImplementsAttr : public DeclAttribute {
17221722
DeclName MemberName);
17231723

17241724
ProtocolDecl *getProtocol(DeclContext *dc) const;
1725+
std::optional<ProtocolDecl *> getCachedProtocol(DeclContext *dc) const;
17251726
TypeRepr *getProtocolTypeRepr() const { return TyR; }
17261727

17271728
DeclName getMemberName() const { return MemberName; }

include/swift/AST/CatchNode.h

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ class CatchNode: public llvm::PointerUnion<
4545
/// needs to be inferred.
4646
Type getExplicitCaughtType(ASTContext &ctx) const;
4747

48+
/// Returns the explicitly-specified type error that will be caught by this
49+
/// catch node, or `nullopt` if it has not yet been computed. This should only
50+
/// be used for dumping.
51+
std::optional<Type> getCachedExplicitCaughtType(ASTContext &ctx) const;
52+
4853
friend llvm::hash_code hash_value(CatchNode catchNode) {
4954
using llvm::hash_value;
5055
return hash_value(catchNode.getOpaqueValue());

include/swift/AST/Decl.h

+16
Original file line numberDiff line numberDiff line change
@@ -3326,6 +3326,10 @@ class ValueDecl : public Decl {
33263326
/// Get the decl for this value's opaque result type, if it has one.
33273327
OpaqueTypeDecl *getOpaqueResultTypeDecl() const;
33283328

3329+
/// Gets the decl for this value's opaque result type if it has already been
3330+
/// computed, or `nullopt` otherwise. This should only be used for dumping.
3331+
std::optional<OpaqueTypeDecl *> getCachedOpaqueResultTypeDecl() const;
3332+
33293333
/// Get the representative for this value's opaque result type, if it has one.
33303334
/// Returns a `TypeRepr` instead of an `OpaqueReturnTypeRepr` because 'some'
33313335
/// types might appear in one or more structural positions, e.g. (some P,
@@ -7769,6 +7773,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
77697773
/// Retrieves the thrown interface type.
77707774
Type getThrownInterfaceType() const;
77717775

7776+
/// Returns the thrown interface type of this function if it has already been
7777+
/// computed, otherwise `nullopt`. This should only be used for dumping.
7778+
std::optional<Type> getCachedThrownInterfaceType() const;
7779+
77727780
/// Retrieve the "effective" thrown interface type, or std::nullopt if
77737781
/// this function cannot throw.
77747782
///
@@ -8329,6 +8337,10 @@ class FuncDecl : public AbstractFunctionDecl {
83298337
/// Retrieve the result interface type of this function.
83308338
Type getResultInterfaceType() const;
83318339

8340+
/// Returns the result interface type of this function if it has already been
8341+
/// computed, otherwise `nullopt`. This should only be used for dumping.
8342+
std::optional<Type> getCachedResultInterfaceType() const;
8343+
83328344
/// isUnaryOperator - Determine whether this is a unary operator
83338345
/// implementation. This check is a syntactic rather than type-based check,
83348346
/// which looks at the number of parameters specified, in order to allow
@@ -9529,6 +9541,10 @@ class MacroDecl : public GenericContext, public ValueDecl {
95299541
/// Retrieve the interface type produced when expanding this macro.
95309542
Type getResultInterfaceType() const;
95319543

9544+
/// Returns the result interface type of this macro if it has already been
9545+
/// computed, otherwise `nullopt`. This should only be used for dumping.
9546+
std::optional<Type> getCachedResultInterfaceType() const;
9547+
95329548
/// Determine the contexts in which this macro can be applied.
95339549
MacroRoles getMacroRoles() const;
95349550

lib/AST/ASTDumper.cpp

+49-29
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,17 @@ namespace {
16711671
}
16721672
}
16731673

1674+
/// Prints a `Type` if it is present, falling back to the `TypeRepr`
1675+
/// otherwise (and lastly, doing nothing if the `TypeRepr` was also null).
1676+
void printTypeOrTypeRepr(std::optional<Type> Ty, TypeRepr *Repr,
1677+
Label label) {
1678+
if (Ty.has_value()) {
1679+
printTypeField(*Ty, label);
1680+
} else if (Repr) {
1681+
printRec(Repr, label);
1682+
}
1683+
}
1684+
16741685
void printThrowDest(ThrownErrorDestination throws, bool wantNothrow) {
16751686
if (!throws) {
16761687
if (wantNothrow)
@@ -1681,11 +1692,26 @@ namespace {
16811692

16821693
auto thrownError = throws.getThrownErrorType();
16831694
auto contextError = throws.getContextErrorType();
1695+
if (Writer.isParsable()) {
1696+
// For parsable outputs, just print the full thrown and contextual error
1697+
// information as a nice structured object, even if they're the same.
1698+
printRecArbitrary(
1699+
[&](Label label) {
1700+
printHead("thrown_error_destination", IdentifierColor, label);
1701+
printTypeField(thrownError, Label::always("thrown_type"));
1702+
printTypeField(contextError, Label::always("context_type"));
1703+
printFoot();
1704+
},
1705+
Label::always("throws"));
1706+
return;
1707+
}
1708+
16841709
if (thrownError->isEqual(contextError)) {
1685-
// No translation of the thrown error type is required, so ony print
1710+
// No translation of the thrown error type is required, so only print
16861711
// the thrown error type.
16871712
Type errorExistentialType =
16881713
contextError->getASTContext().getErrorExistentialType();
1714+
16891715
if (errorExistentialType && thrownError->isEqual(errorExistentialType))
16901716
printFlag("throws", ExprModifierColor);
16911717
else {
@@ -2456,29 +2482,20 @@ namespace {
24562482
if (auto *P = D->getImplicitSelfDecl()) {
24572483
printRec(P, Label::optional("implicit_self_decl"));
24582484
}
2459-
printRec(D->getParameters(), Label::optional("params"),
2460-
&D->getASTContext());
2461-
24622485
if (auto FD = dyn_cast<FuncDecl>(D)) {
2463-
if (Writer.isParsable() && FD->hasInterfaceType()) {
2464-
printTypeField(FD->getResultInterfaceType(), Label::always("result"));
2465-
if (auto opaque = FD->getOpaqueResultTypeDecl()) {
2466-
printRec(opaque, Label::always("opaque_result_decl"));
2467-
}
2468-
} else if (FD->getResultTypeRepr()) {
2469-
printRec(FD->getResultTypeRepr(), Label::always("result"));
2470-
if (auto opaque = FD->getOpaqueResultTypeDecl()) {
2471-
printRec(opaque, Label::always("opaque_result_decl"));
2472-
}
2486+
printTypeOrTypeRepr(FD->getCachedResultInterfaceType(),
2487+
FD->getResultTypeRepr(), Label::always("result"));
2488+
if (auto opaque = FD->getCachedOpaqueResultTypeDecl();
2489+
opaque && *opaque != nullptr) {
2490+
printRec(*opaque, Label::always("opaque_result_decl"));
24732491
}
24742492
}
24752493

2476-
if (Writer.isParsable() && D->hasInterfaceType()) {
2477-
printTypeField(D->getThrownInterfaceType(),
2478-
Label::always("thrown_type"));
2479-
} else if (auto thrownTypeRepr = D->getThrownTypeRepr()) {
2480-
printRec(thrownTypeRepr,Label::always("thrown_type"));
2481-
}
2494+
printTypeOrTypeRepr(D->getCachedThrownInterfaceType(),
2495+
D->getThrownTypeRepr(), Label::always("thrown_type"));
2496+
2497+
printRec(D->getParameters(), Label::optional("params"),
2498+
&D->getASTContext());
24822499

24832500
if (auto fac = D->getForeignAsyncConvention()) {
24842501
printRecArbitrary([&](Label label) {
@@ -2653,10 +2670,8 @@ namespace {
26532670
printAttributes(MD);
26542671
printRec(MD->getParameterList(), Label::optional("params"),
26552672
&MD->getASTContext());
2656-
if (Writer.isParsable() && MD->getResultInterfaceType())
2657-
printTypeField(MD->getResultInterfaceType(), Label::always("result"));
2658-
else if (MD->resultType.getTypeRepr())
2659-
printRec(MD->resultType.getTypeRepr(), Label::always("result"));
2673+
printTypeOrTypeRepr(MD->getCachedResultInterfaceType(),
2674+
MD->getResultTypeRepr(), Label::always("result"));
26602675
printRec(MD->definition, Label::always("definition"));
26612676
printFoot();
26622677
}
@@ -4861,10 +4876,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
48614876
}
48624877
void visitCustomAttr(CustomAttr *Attr, Label label) {
48634878
printCommon(Attr, "custom_attr", label);
4864-
if (Writer.isParsable())
4865-
printTypeField(Attr->getType(), Label::always("type"));
4866-
else
4879+
printTypeField(Attr->getType(), Label::always("type"));
4880+
if (!Writer.isParsable()) {
4881+
// The type has the semantic information we want for parsable outputs, so
4882+
// omit the `TypeRepr` there.
48674883
printRec(Attr->getTypeRepr(), Label::optional("type_repr"));
4884+
}
48684885
if (Attr->getArgs())
48694886
printRec(Attr->getArgs(), Label::optional("args"));
48704887
printFoot();
@@ -4925,8 +4942,11 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49254942
void visitImplementsAttr(ImplementsAttr *Attr, Label label) {
49264943
printCommon(Attr, "implements_attr", label);
49274944
if (Writer.isParsable()) {
4928-
printFieldQuoted(declUSR(Attr->getProtocol(DC)),
4929-
Label::always("protocol"));
4945+
// Print the resolved protocol's USR in parsable outputs, not the
4946+
// TypeRepr.
4947+
if (auto PD = Attr->getCachedProtocol(DC); PD && *PD != nullptr) {
4948+
printFieldQuoted(declUSR(*PD), Label::always("protocol"));
4949+
}
49304950
} else {
49314951
printRec(Attr->getProtocolTypeRepr(), Label::always("protocol"));
49324952
}

lib/AST/Attr.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,14 @@ ProtocolDecl *ImplementsAttr::getProtocol(DeclContext *dc) const {
27342734
ImplementsAttrProtocolRequest{this, dc}, nullptr);
27352735
}
27362736

2737+
std::optional<ProtocolDecl *>
2738+
ImplementsAttr::getCachedProtocol(DeclContext *dc) const {
2739+
ImplementsAttrProtocolRequest request{this, dc};
2740+
if (dc->getASTContext().evaluator.hasCachedResult(request))
2741+
return getProtocol(dc);
2742+
return std::nullopt;
2743+
}
2744+
27372745
CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
27382746
CustomAttributeInitializer *initContext,
27392747
ArgumentList *argList, bool implicit)

lib/AST/Decl.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,14 @@ Type AbstractFunctionDecl::getThrownInterfaceType() const {
11021102
return CatchNode(mutableThis).getExplicitCaughtType(getASTContext());
11031103
}
11041104

1105+
std::optional<Type> AbstractFunctionDecl::getCachedThrownInterfaceType() const {
1106+
if (!getThrownTypeRepr())
1107+
return ThrownType.getType();
1108+
1109+
auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
1110+
return CatchNode(mutableThis).getCachedExplicitCaughtType(getASTContext());
1111+
}
1112+
11051113
std::optional<Type> AbstractFunctionDecl::getEffectiveThrownErrorType() const {
11061114
// FIXME: Only getters can have thrown error types right now, and DidSet
11071115
// has a cyclic reference if we try to get its interface type here. Find a
@@ -3934,6 +3942,12 @@ OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const {
39343942
nullptr);
39353943
}
39363944

3945+
std::optional<OpaqueTypeDecl *>
3946+
ValueDecl::getCachedOpaqueResultTypeDecl() const {
3947+
return OpaqueResultTypeRequest{const_cast<ValueDecl *>(this)}
3948+
.getCachedResult();
3949+
}
3950+
39373951
bool ValueDecl::isObjC() const {
39383952
ASTContext &ctx = getASTContext();
39393953
return evaluateOrDefault(ctx.evaluator,
@@ -10768,6 +10782,11 @@ Type FuncDecl::getResultInterfaceType() const {
1076810782
return ErrorType::get(ctx);
1076910783
}
1077010784

10785+
std::optional<Type> FuncDecl::getCachedResultInterfaceType() const {
10786+
auto mutableThis = const_cast<FuncDecl *>(this);
10787+
return ResultTypeRequest{mutableThis}.getCachedResult();
10788+
}
10789+
1077110790
bool FuncDecl::isUnaryOperator() const {
1077210791
if (!isOperator())
1077310792
return false;
@@ -11925,6 +11944,11 @@ Type MacroDecl::getResultInterfaceType() const {
1192511944
return ErrorType::get(ctx);
1192611945
}
1192711946

11947+
std::optional<Type> MacroDecl::getCachedResultInterfaceType() const {
11948+
auto mutableThis = const_cast<MacroDecl *>(this);
11949+
return ResultTypeRequest{mutableThis}.getCachedResult();
11950+
}
11951+
1192811952
SourceRange MacroDecl::getSourceRange() const {
1192911953
SourceLoc endLoc = getNameLoc();
1193011954
if (parameterList)
@@ -12355,6 +12379,11 @@ Type CatchNode::getExplicitCaughtType(ASTContext &ctx) const {
1235512379
ctx.evaluator, ExplicitCaughtTypeRequest{&ctx, *this}, Type());
1235612380
}
1235712381

12382+
std::optional<Type>
12383+
CatchNode::getCachedExplicitCaughtType(ASTContext &ctx) const {
12384+
return ExplicitCaughtTypeRequest{&ctx, *this}.getCachedResult();
12385+
}
12386+
1235812387
void swift::simple_display(llvm::raw_ostream &out, CatchNode catchNode) {
1235912388
out << "catch node";
1236012389
}

test/Frontend/module-alias-dump-ast.swift

-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
// RUN: %target-swift-frontend -dump-ast %t/FileLib.swift -module-alias XLogging=AppleLogging -I %t > %t/result-ast.output
1414

1515
// RUN: %FileCheck %s -input-file %t/result-ast.output -check-prefix CHECK-AST
16-
// CHECK-AST-NOT: bind="XLogging"
1716
// CHECK-AST-NOT: module<XLogging>
1817
// CHECK-AST-NOT: decl="XLogging"
19-
// CHECK-AST: type_unqualified_ident id="XLogging" bind="AppleLogging"
2018
// CHECK-AST: module<AppleLogging>
2119
// CHECK-AST: decl="AppleLogging"
2220

0 commit comments

Comments
 (0)