Skip to content

Commit 665db87

Browse files
author
Harlan
authored
[InterfaceGen] Print bodies of inlinable functions in textual interfaces (#19224)
* Introduce stored inlinable function bodies * Remove serialization changes * [InterfaceGen] Print inlinable function bodies * Clean up a little bit and add test * Undo changes to InlinableText * Add serialization and deserialization for inlinable body text * Allow parser to parse accessor bodies in interfaces * Fix some tests * Fix remaining tests * Add tests for usableFromInline decls * Add comments * Clean up function body printing throughout * Add tests for subscripts * Remove comment about subscript inlinable text * Address some comments * Handle lack of @objc on Linux
1 parent e034025 commit 665db87

19 files changed

+477
-115
lines changed

include/swift/AST/Decl.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4977,7 +4977,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
49774977
TypeChecked,
49784978

49794979
/// This is a memberwise initializer that will be synthesized by SILGen.
4980-
MemberwiseInitializer
4980+
MemberwiseInitializer,
4981+
4982+
/// Function body text was deserialized from a .swiftmodule.
4983+
Deserialized
49814984

49824985
// This enum currently needs to fit in a 3-bit bitfield.
49834986
};
@@ -4999,6 +5002,9 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
49995002
/// BodyKind::TypeChecked.
50005003
BraceStmt *Body;
50015004

5005+
/// This enum member is active if getBodyKind() is BodyKind::Deserialized.
5006+
StringRef BodyStringRepresentation;
5007+
50025008
/// This enum member is active if getBodyKind() == BodyKind::Synthesize.
50035009
BodySynthesizer Synthesizer;
50045010

@@ -5093,6 +5099,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
50935099
return getBodyKind() != BodyKind::None;
50945100
}
50955101

5102+
/// Returns true if the text of this function's body can be retrieved either
5103+
/// by extracting the text from the source buffer or reading the inlinable
5104+
/// body from a deserialized swiftmodule.
5105+
bool hasInlinableBodyText() const;
5106+
50965107
/// Returns the function body, if it was parsed, or nullptr otherwise.
50975108
///
50985109
/// Note that a null return value does not imply that the source code did not
@@ -5156,6 +5167,18 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
51565167
setBodyKind(BodyKind::TypeChecked);
51575168
}
51585169

5170+
/// Gets the body of this function, stripping the unused portions of #if
5171+
/// configs inside the body. If this function was not deserialized from a
5172+
/// .swiftmodule, this body is reconstructed from the original
5173+
/// source buffer.
5174+
StringRef getInlinableBodyText(SmallVectorImpl<char> &scratch) const;
5175+
5176+
void setBodyStringRepresentation(StringRef body) {
5177+
assert(getBodyKind() == BodyKind::None);
5178+
setBodyKind(BodyKind::Deserialized);
5179+
BodyStringRepresentation = body;
5180+
}
5181+
51595182
bool isBodyTypeChecked() const {
51605183
return getBodyKind() == BodyKind::TypeChecked;
51615184
}

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <vector>
2424

2525
namespace swift {
26+
class ASTPrinter;
2627
class GenericEnvironment;
2728
class CanType;
2829
class Decl;
@@ -356,10 +357,9 @@ struct PrintOptions {
356357
QualifyNestedDeclarations ShouldQualifyNestedDeclarations =
357358
QualifyNestedDeclarations::Never;
358359

359-
/// \brief If this is not \c nullptr then functions (including accessors and
360-
/// constructors) will be printed with a body that is determined by this
361-
/// function.
362-
std::function<std::string(const ValueDecl *)> FunctionBody;
360+
/// \brief If this is not \c nullptr then function bodies (including accessors
361+
/// and constructors) will be printed by this function.
362+
std::function<void(const ValueDecl *, ASTPrinter &)> FunctionBody;
363363

364364
BracketOptions BracketOptions;
365365

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 246)
180180
OTHER(PROTOCOL_CONFORMANCE_XREF, 247)
181181
OTHER(MEMBERS, 248)
182182
OTHER(XREF, 249)
183+
OTHER(INLINABLE_BODY_TEXT, 250)
183184

184185
#undef RECORD
185186
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL

include/swift/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ class ModuleFile
884884

885885
/// Reads a foreign error conformance from \c DeclTypeCursor, if present.
886886
Optional<ForeignErrorConvention> maybeReadForeignErrorConvention();
887+
888+
/// Reads inlinable body text from \c DeclTypeCursor, if present.
889+
Optional<StringRef> maybeReadInlinableBodyText();
887890
};
888891

889892
template <typename T, typename RawData>

include/swift/Serialization/ModuleFormat.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 443; // Last change: serialize unsubstituted type alias type
58+
const uint16_t VERSION_MINOR = 444; // Last change: inlinable body text
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -979,8 +979,11 @@ namespace decls_block {
979979
BCVBR<5>, // number of parameter name components
980980
BCArray<IdentifierIDField> // name components,
981981
// followed by TypeID dependencies
982-
// Trailed by its generic parameters, if any, followed by the parameter
983-
// patterns.
982+
// This record is trailed by:
983+
// - its generic parameters, if any
984+
// - its parameter patterns,
985+
// - the foreign error convention, if any
986+
// - inlinable body text, if any
984987
>;
985988

986989
using VarLayout = BCRecordLayout<
@@ -1044,6 +1047,8 @@ namespace decls_block {
10441047
// - its _silgen_name, if any
10451048
// - its generic parameters, if any
10461049
// - body parameter patterns
1050+
// - the foreign error convention, if any
1051+
// - inlinable body text, if any
10471052
>;
10481053

10491054
// TODO: remove the unnecessary FuncDecl components here
@@ -1073,6 +1078,8 @@ namespace decls_block {
10731078
// - its _silgen_name, if any
10741079
// - its generic parameters, if any
10751080
// - body parameter patterns
1081+
// - the foreign error convention, if any
1082+
// - inlinable body text, if any
10761083
>;
10771084

10781085
using PatternBindingLayout = BCRecordLayout<
@@ -1176,6 +1183,12 @@ namespace decls_block {
11761183
BCFixed<1>, // implicit?
11771184
BCFixed<1>, // objc?
11781185
GenericEnvironmentIDField // generic environment
1186+
// This record is trailed by its inlinable body text
1187+
>;
1188+
1189+
using InlinableBodyTextLayout = BCRecordLayout<
1190+
INLINABLE_BODY_TEXT,
1191+
BCBlob // body text
11791192
>;
11801193

11811194
using ParameterListLayout = BCRecordLayout<

lib/AST/ASTPrinter.cpp

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ PrintOptions PrintOptions::printTextualInterfaceFile() {
8181
result.SkipImports = true;
8282
result.OmitNameOfInaccessibleProperties = true;
8383

84+
result.FunctionBody = [](const ValueDecl *decl, ASTPrinter &printer) {
85+
auto AFD = dyn_cast<AbstractFunctionDecl>(decl);
86+
if (!AFD || !AFD->hasInlinableBodyText()) return;
87+
if (AFD->getResilienceExpansion() != ResilienceExpansion::Minimal)
88+
return;
89+
SmallString<128> scratch;
90+
printer << " " << AFD->getInlinableBodyText(scratch);
91+
};
92+
8493
class ShouldPrintForTextualInterface : public ShouldPrintChecker {
8594
bool shouldPrint(const Decl *D, const PrintOptions &options) override {
8695
// Skip anything that isn't 'public' or '@usableFromInline'.
@@ -645,6 +654,7 @@ class PrintAST : public ASTVisitor<PrintAST> {
645654

646655
void printAttributes(const Decl *D);
647656
void printTypedPattern(const TypedPattern *TP);
657+
void printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty = true);
648658

649659
public:
650660
void printPattern(const Pattern *pattern);
@@ -686,6 +696,7 @@ class PrintAST : public ASTVisitor<PrintAST> {
686696
void printGenericDeclGenericParams(GenericContext *decl);
687697
void printGenericDeclGenericRequirements(GenericContext *decl);
688698
void printInherited(const Decl *decl);
699+
void printBodyIfNecessary(const AbstractFunctionDecl *decl);
689700

690701
void printEnumElement(EnumElementDecl *elt);
691702

@@ -1471,6 +1482,29 @@ bool PrintAST::shouldPrint(const Decl *D, bool Notify) {
14711482
return Result;
14721483
}
14731484

1485+
void PrintAST::printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty) {
1486+
Printer << "{";
1487+
if (printASTNodes(stmt->getElements()) || newlineIfEmpty) {
1488+
Printer.printNewline();
1489+
indent();
1490+
}
1491+
Printer << "}";
1492+
}
1493+
1494+
void PrintAST::printBodyIfNecessary(const AbstractFunctionDecl *decl) {
1495+
if (auto BodyFunc = Options.FunctionBody) {
1496+
BodyFunc(decl, Printer);
1497+
indent();
1498+
return;
1499+
}
1500+
1501+
if (!Options.FunctionDefinitions || !decl->getBody())
1502+
return;
1503+
1504+
Printer << " ";
1505+
printBraceStmt(decl->getBody(), /*newlineIfEmpty*/!isa<AccessorDecl>(decl));
1506+
}
1507+
14741508
static bool isAccessorAssumedNonMutating(AccessorKind kind) {
14751509
switch (kind) {
14761510
case AccessorKind::Get:
@@ -1630,26 +1664,37 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
16301664
Printer << " ";
16311665
Printer.printKeyword(getAccessorLabel(Accessor));
16321666
} else {
1633-
Printer.printNewline();
1634-
IndentRAII IndentMore(*this);
1667+
{
1668+
IndentRAII IndentMore(*this);
1669+
indent();
1670+
visit(Accessor);
1671+
}
16351672
indent();
1636-
visit(Accessor);
1673+
Printer.printNewline();
16371674
}
16381675
};
16391676

1640-
Printer << " {";
16411677
if ((PrintAbstract ||
16421678
(impl.getReadImpl() == ReadImplKind::Get && ASD->getGetter())) &&
16431679
!ASD->supportsMutation() && !ASD->isGetterMutating() &&
16441680
PrintAccessorBody && !Options.FunctionDefinitions) {
16451681
// Omit the 'get' keyword. Directly print getter
16461682
if (auto BodyFunc = Options.FunctionBody) {
1647-
Printer.printNewline();
1648-
IndentRAII IndentBody(*this);
1683+
BodyFunc(ASD->getGetter(), Printer);
16491684
indent();
1650-
Printer << BodyFunc(ASD->getGetter());
1685+
return;
16511686
}
1652-
} else if (PrintAbstract) {
1687+
Printer.printNewline();
1688+
indent();
1689+
return;
1690+
}
1691+
1692+
Printer << " {";
1693+
1694+
if (PrintAccessorBody)
1695+
Printer.printNewline();
1696+
1697+
if (PrintAbstract) {
16531698
PrintAccessor(ASD->getGetter());
16541699
if (ASD->supportsMutation())
16551700
PrintAccessor(ASD->getSetter());
@@ -1693,12 +1738,16 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
16931738
break;
16941739
}
16951740
}
1696-
if (PrintAccessorBody) {
1697-
Printer.printNewline();
1698-
indent();
1699-
} else
1741+
1742+
if (!PrintAccessorBody)
17001743
Printer << " ";
1744+
17011745
Printer << "}";
1746+
1747+
if (!PrintAbstract)
1748+
Printer.printNewline();
1749+
1750+
indent();
17021751
}
17031752

17041753
void PrintAST::printMembersOfDecl(Decl *D, bool needComma,
@@ -2497,7 +2546,6 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
24972546
[&]{
24982547
Printer << getAccessorLabel(decl);
24992548
});
2500-
Printer << " {";
25012549
break;
25022550
case AccessorKind::Set:
25032551
case AccessorKind::WillSet:
@@ -2515,24 +2563,9 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
25152563
}
25162564
}
25172565
});
2518-
Printer << " {";
25192566
}
2520-
if (auto BodyFunc = Options.FunctionBody) {
2521-
{
2522-
IndentRAII IndentBody(*this);
2523-
indent();
2524-
Printer.printNewline();
2525-
Printer << BodyFunc(decl);
2526-
}
2527-
indent();
2528-
Printer.printNewline();
2529-
} else if (Options.FunctionDefinitions && decl->getBody()) {
2530-
if (printASTNodes(decl->getBody()->getElements())) {
2531-
Printer.printNewline();
2532-
indent();
2533-
}
2534-
}
2535-
Printer << "}";
2567+
2568+
printBodyIfNecessary(decl);
25362569
}
25372570

25382571
void PrintAST::visitFuncDecl(FuncDecl *decl) {
@@ -2604,22 +2637,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
26042637
printGenericDeclGenericRequirements(decl);
26052638
}
26062639

2607-
if (auto BodyFunc = Options.FunctionBody) {
2608-
Printer << " {";
2609-
Printer.printNewline();
2610-
{
2611-
IndentRAII IndentBody(*this);
2612-
indent();
2613-
Printer << BodyFunc(decl);
2614-
}
2615-
indent();
2616-
Printer.printNewline();
2617-
Printer << "}";
2618-
2619-
} else if (Options.FunctionDefinitions && decl->getBody()) {
2620-
Printer << " ";
2621-
visit(decl->getBody());
2622-
}
2640+
printBodyIfNecessary(decl);
26232641
}
26242642

26252643
void PrintAST::printEnumElement(EnumElementDecl *elt) {
@@ -2788,21 +2806,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
27882806

27892807
printGenericDeclGenericRequirements(decl);
27902808

2791-
if (auto BodyFunc = Options.FunctionBody) {
2792-
Printer << " {";
2793-
{
2794-
Printer.printNewline();
2795-
IndentRAII IndentBody(*this);
2796-
indent();
2797-
Printer << BodyFunc(decl);
2798-
}
2799-
indent();
2800-
Printer.printNewline();
2801-
Printer << "}";
2802-
} else if (Options.FunctionDefinitions && decl->getBody()) {
2803-
Printer << " ";
2804-
visit(decl->getBody());
2805-
}
2809+
printBodyIfNecessary(decl);
28062810
}
28072811

28082812
void PrintAST::visitDestructorDecl(DestructorDecl *decl) {
@@ -2814,12 +2818,7 @@ void PrintAST::visitDestructorDecl(DestructorDecl *decl) {
28142818
Printer << "deinit";
28152819
});
28162820

2817-
if (!Options.FunctionDefinitions || !decl->getBody()) {
2818-
return;
2819-
}
2820-
2821-
Printer << " ";
2822-
visit(decl->getBody());
2821+
printBodyIfNecessary(decl);
28232822
}
28242823

28252824
void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
@@ -2929,11 +2928,7 @@ void PrintAST::visitMissingMemberDecl(MissingMemberDecl *decl) {
29292928
}
29302929

29312930
void PrintAST::visitBraceStmt(BraceStmt *stmt) {
2932-
Printer << "{";
2933-
printASTNodes(stmt->getElements());
2934-
Printer.printNewline();
2935-
indent();
2936-
Printer << "}";
2931+
printBraceStmt(stmt);
29372932
}
29382933

29392934
void PrintAST::visitReturnStmt(ReturnStmt *stmt) {

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ class Verifier : public ASTWalker {
490490
case AbstractFunctionDecl::BodyKind::TypeChecked:
491491
case AbstractFunctionDecl::BodyKind::Skipped:
492492
case AbstractFunctionDecl::BodyKind::MemberwiseInitializer:
493+
case AbstractFunctionDecl::BodyKind::Deserialized:
493494
return true;
494495

495496
case AbstractFunctionDecl::BodyKind::Unparsed:

0 commit comments

Comments
 (0)