Skip to content

Commit 2211680

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 1ec8492 commit 2211680

File tree

7 files changed

+108
-31
lines changed

7 files changed

+108
-31
lines changed

include/swift/AST/Attr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,7 @@ class ImplementsAttr : public DeclAttribute {
17111711
DeclName MemberName);
17121712

17131713
ProtocolDecl *getProtocol(DeclContext *dc) const;
1714+
std::optional<ProtocolDecl *> getCachedProtocol(DeclContext *dc) const;
17141715
TypeRepr *getProtocolTypeRepr() const { return TyR; }
17151716

17161717
DeclName getMemberName() const { return MemberName; }

include/swift/AST/CatchNode.h

Lines changed: 5 additions & 0 deletions
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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,6 +3321,10 @@ class ValueDecl : public Decl {
33213321
/// Get the decl for this value's opaque result type, if it has one.
33223322
OpaqueTypeDecl *getOpaqueResultTypeDecl() const;
33233323

3324+
/// Gets the decl for this value's opaque result type if it has already been
3325+
/// computed, or `nullopt` otherwise. This should only be used for dumping.
3326+
std::optional<OpaqueTypeDecl *> getCachedOpaqueResultTypeDecl() const;
3327+
33243328
/// Get the representative for this value's opaque result type, if it has one.
33253329
/// Returns a `TypeRepr` instead of an `OpaqueReturnTypeRepr` because 'some'
33263330
/// types might appear in one or more structural positions, e.g. (some P,
@@ -7764,6 +7768,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
77647768
/// Retrieves the thrown interface type.
77657769
Type getThrownInterfaceType() const;
77667770

7771+
/// Returns the thrown interface type of this function if it has already been
7772+
/// computed, otherwise `nullopt`. This should only be used for dumping.
7773+
std::optional<Type> getCachedThrownInterfaceType() const;
7774+
77677775
/// Retrieve the "effective" thrown interface type, or std::nullopt if
77687776
/// this function cannot throw.
77697777
///
@@ -8324,6 +8332,10 @@ class FuncDecl : public AbstractFunctionDecl {
83248332
/// Retrieve the result interface type of this function.
83258333
Type getResultInterfaceType() const;
83268334

8335+
/// Returns the result interface type of this function if it has already been
8336+
/// computed, otherwise `nullopt`. This should only be used for dumping.
8337+
std::optional<Type> getCachedResultInterfaceType() const;
8338+
83278339
/// isUnaryOperator - Determine whether this is a unary operator
83288340
/// implementation. This check is a syntactic rather than type-based check,
83298341
/// which looks at the number of parameters specified, in order to allow
@@ -9524,6 +9536,10 @@ class MacroDecl : public GenericContext, public ValueDecl {
95249536
/// Retrieve the interface type produced when expanding this macro.
95259537
Type getResultInterfaceType() const;
95269538

9539+
/// Returns the result interface type of this macro if it has already been
9540+
/// computed, otherwise `nullopt`. This should only be used for dumping.
9541+
std::optional<Type> getCachedResultInterfaceType() const;
9542+
95279543
/// Determine the contexts in which this macro can be applied.
95289544
MacroRoles getMacroRoles() const;
95299545

lib/AST/ASTDumper.cpp

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,17 @@ namespace {
16631663
}
16641664
}
16651665

1666+
/// Prints a `Type` if it is present, falling back to the `TypeRepr`
1667+
/// otherwise (and lastly, doing nothing if the `TypeRepr` was also null).
1668+
void printTypeOrTypeRepr(std::optional<Type> Ty, TypeRepr *Repr,
1669+
Label label) {
1670+
if (Ty.has_value()) {
1671+
printTypeField(*Ty, label);
1672+
} else if (Repr) {
1673+
printRec(Repr, label);
1674+
}
1675+
}
1676+
16661677
void printThrowDest(ThrownErrorDestination throws, bool wantNothrow) {
16671678
if (!throws) {
16681679
if (wantNothrow)
@@ -1673,11 +1684,26 @@ namespace {
16731684

16741685
auto thrownError = throws.getThrownErrorType();
16751686
auto contextError = throws.getContextErrorType();
1687+
if (Writer.isParsable()) {
1688+
// For parsable outputs, just print the full thrown and contextual error
1689+
// information as a nice structured object, even if they're the same.
1690+
printRecArbitrary(
1691+
[&](Label label) {
1692+
printHead("thrown_error_destination", IdentifierColor, label);
1693+
printTypeField(thrownError, Label::always("thrown_type"));
1694+
printTypeField(contextError, Label::always("context_type"));
1695+
printFoot();
1696+
},
1697+
Label::always("throws"));
1698+
return;
1699+
}
1700+
16761701
if (thrownError->isEqual(contextError)) {
1677-
// No translation of the thrown error type is required, so ony print
1702+
// No translation of the thrown error type is required, so only print
16781703
// the thrown error type.
16791704
Type errorExistentialType =
16801705
contextError->getASTContext().getErrorExistentialType();
1706+
16811707
if (errorExistentialType && thrownError->isEqual(errorExistentialType))
16821708
printFlag("throws", ExprModifierColor);
16831709
else {
@@ -2448,29 +2474,20 @@ namespace {
24482474
if (auto *P = D->getImplicitSelfDecl()) {
24492475
printRec(P, Label::optional("implicit_self_decl"));
24502476
}
2451-
printRec(D->getParameters(), Label::optional("params"),
2452-
&D->getASTContext());
2453-
24542477
if (auto FD = dyn_cast<FuncDecl>(D)) {
2455-
if (Writer.isParsable() && FD->hasInterfaceType()) {
2456-
printTypeField(FD->getResultInterfaceType(), Label::always("result"));
2457-
if (auto opaque = FD->getOpaqueResultTypeDecl()) {
2458-
printRec(opaque, Label::always("opaque_result_decl"));
2459-
}
2460-
} else if (FD->getResultTypeRepr()) {
2461-
printRec(FD->getResultTypeRepr(), Label::always("result"));
2462-
if (auto opaque = FD->getOpaqueResultTypeDecl()) {
2463-
printRec(opaque, Label::always("opaque_result_decl"));
2464-
}
2478+
printTypeOrTypeRepr(FD->getCachedResultInterfaceType(),
2479+
FD->getResultTypeRepr(), Label::always("result"));
2480+
if (auto opaque = FD->getCachedOpaqueResultTypeDecl();
2481+
opaque && *opaque != nullptr) {
2482+
printRec(*opaque, Label::always("opaque_result_decl"));
24652483
}
24662484
}
24672485

2468-
if (Writer.isParsable() && D->hasInterfaceType()) {
2469-
printTypeField(D->getThrownInterfaceType(),
2470-
Label::always("thrown_type"));
2471-
} else if (auto thrownTypeRepr = D->getThrownTypeRepr()) {
2472-
printRec(thrownTypeRepr,Label::always("thrown_type"));
2473-
}
2486+
printTypeOrTypeRepr(D->getCachedThrownInterfaceType(),
2487+
D->getThrownTypeRepr(), Label::always("thrown_type"));
2488+
2489+
printRec(D->getParameters(), Label::optional("params"),
2490+
&D->getASTContext());
24742491

24752492
if (auto fac = D->getForeignAsyncConvention()) {
24762493
printRecArbitrary([&](Label label) {
@@ -2645,10 +2662,8 @@ namespace {
26452662
printAttributes(MD);
26462663
printRec(MD->getParameterList(), Label::optional("params"),
26472664
&MD->getASTContext());
2648-
if (Writer.isParsable() && MD->getResultInterfaceType())
2649-
printTypeField(MD->getResultInterfaceType(), Label::always("result"));
2650-
else if (MD->resultType.getTypeRepr())
2651-
printRec(MD->resultType.getTypeRepr(), Label::always("result"));
2665+
printTypeOrTypeRepr(MD->getCachedResultInterfaceType(),
2666+
MD->getResultTypeRepr(), Label::always("result"));
26522667
printRec(MD->definition, Label::always("definition"));
26532668
printFoot();
26542669
}
@@ -4851,10 +4866,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
48514866
}
48524867
void visitCustomAttr(CustomAttr *Attr, Label label) {
48534868
printCommon(Attr, "custom_attr", label);
4854-
if (Writer.isParsable())
4855-
printTypeField(Attr->getType(), Label::always("type"));
4856-
else
4869+
printTypeField(Attr->getType(), Label::always("type"));
4870+
if (!Writer.isParsable()) {
4871+
// The type has the semantic information we want for parsable outputs, so
4872+
// omit the `TypeRepr` there.
48574873
printRec(Attr->getTypeRepr(), Label::optional("type_repr"));
4874+
}
48584875
if (Attr->getArgs())
48594876
printRec(Attr->getArgs(), Label::optional("args"));
48604877
printFoot();
@@ -4915,8 +4932,11 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49154932
void visitImplementsAttr(ImplementsAttr *Attr, Label label) {
49164933
printCommon(Attr, "implements_attr", label);
49174934
if (Writer.isParsable()) {
4918-
printFieldQuoted(declUSR(Attr->getProtocol(DC)),
4919-
Label::always("protocol"));
4935+
// Print the resolved protocol's USR in parsable outputs, not the
4936+
// TypeRepr.
4937+
if (auto PD = Attr->getCachedProtocol(DC); PD && *PD != nullptr) {
4938+
printFieldQuoted(declUSR(*PD), Label::always("protocol"));
4939+
}
49204940
} else {
49214941
printRec(Attr->getProtocolTypeRepr(), Label::always("protocol"));
49224942
}

lib/AST/Attr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,14 @@ ProtocolDecl *ImplementsAttr::getProtocol(DeclContext *dc) const {
27202720
ImplementsAttrProtocolRequest{this, dc}, nullptr);
27212721
}
27222722

2723+
std::optional<ProtocolDecl *>
2724+
ImplementsAttr::getCachedProtocol(DeclContext *dc) const {
2725+
ImplementsAttrProtocolRequest request{this, dc};
2726+
if (dc->getASTContext().evaluator.hasCachedResult(request))
2727+
return getProtocol(dc);
2728+
return std::nullopt;
2729+
}
2730+
27232731
CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
27242732
CustomAttributeInitializer *initContext,
27252733
ArgumentList *argList, bool implicit)

lib/AST/Decl.cpp

Lines changed: 29 additions & 0 deletions
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
@@ -3933,6 +3941,12 @@ OpaqueTypeDecl *ValueDecl::getOpaqueResultTypeDecl() const {
39333941
nullptr);
39343942
}
39353943

3944+
std::optional<OpaqueTypeDecl *>
3945+
ValueDecl::getCachedOpaqueResultTypeDecl() const {
3946+
return OpaqueResultTypeRequest{const_cast<ValueDecl *>(this)}
3947+
.getCachedResult();
3948+
}
3949+
39363950
bool ValueDecl::isObjC() const {
39373951
ASTContext &ctx = getASTContext();
39383952
return evaluateOrDefault(ctx.evaluator,
@@ -10763,6 +10777,11 @@ Type FuncDecl::getResultInterfaceType() const {
1076310777
return ErrorType::get(ctx);
1076410778
}
1076510779

10780+
std::optional<Type> FuncDecl::getCachedResultInterfaceType() const {
10781+
auto mutableThis = const_cast<FuncDecl *>(this);
10782+
return ResultTypeRequest{mutableThis}.getCachedResult();
10783+
}
10784+
1076610785
bool FuncDecl::isUnaryOperator() const {
1076710786
if (!isOperator())
1076810787
return false;
@@ -11920,6 +11939,11 @@ Type MacroDecl::getResultInterfaceType() const {
1192011939
return ErrorType::get(ctx);
1192111940
}
1192211941

11942+
std::optional<Type> MacroDecl::getCachedResultInterfaceType() const {
11943+
auto mutableThis = const_cast<MacroDecl *>(this);
11944+
return ResultTypeRequest{mutableThis}.getCachedResult();
11945+
}
11946+
1192311947
SourceRange MacroDecl::getSourceRange() const {
1192411948
SourceLoc endLoc = getNameLoc();
1192511949
if (parameterList)
@@ -12350,6 +12374,11 @@ Type CatchNode::getExplicitCaughtType(ASTContext &ctx) const {
1235012374
ctx.evaluator, ExplicitCaughtTypeRequest{&ctx, *this}, Type());
1235112375
}
1235212376

12377+
std::optional<Type>
12378+
CatchNode::getCachedExplicitCaughtType(ASTContext &ctx) const {
12379+
return ExplicitCaughtTypeRequest{&ctx, *this}.getCachedResult();
12380+
}
12381+
1235312382
void swift::simple_display(llvm::raw_ostream &out, CatchNode catchNode) {
1235412383
out << "catch node";
1235512384
}

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

Lines changed: 0 additions & 2 deletions
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)