Skip to content

Commit 690409d

Browse files
authored
Merge pull request #26105 from DougGregor/more-lazy-body-synthesis
More lazy body synthesis
2 parents f886945 + f0513ae commit 690409d

16 files changed

+839
-727
lines changed

include/swift/AST/Decl.h

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,7 +5615,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
56155615
}
56165616

56175617
struct BodySynthesizer {
5618-
void (* Fn)(AbstractFunctionDecl *, void *);
5618+
std::pair<BraceStmt *, bool> (* Fn)(AbstractFunctionDecl *, void *);
56195619
void *Context;
56205620
};
56215621

@@ -5748,18 +5748,8 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
57485748
/// have a body for this function.
57495749
///
57505750
/// \sa hasBody()
5751-
BraceStmt *getBody(bool canSynthesize = true) const {
5752-
if (canSynthesize && getBodyKind() == BodyKind::Synthesize) {
5753-
const_cast<AbstractFunctionDecl *>(this)->setBodyKind(BodyKind::None);
5754-
(Synthesizer.Fn)(const_cast<AbstractFunctionDecl *>(this),
5755-
Synthesizer.Context);
5756-
}
5757-
if (getBodyKind() == BodyKind::Parsed ||
5758-
getBodyKind() == BodyKind::TypeChecked) {
5759-
return Body;
5760-
}
5761-
return nullptr;
5762-
}
5751+
BraceStmt *getBody(bool canSynthesize = true) const;
5752+
57635753
void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
57645754
assert(getBodyKind() != BodyKind::Skipped &&
57655755
"cannot set a body if it was skipped");
@@ -5784,8 +5774,12 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
57845774
}
57855775

57865776
/// Note that parsing for the body was delayed.
5787-
void setBodySynthesizer(void (* fn)(AbstractFunctionDecl *, void *),
5788-
void *context = nullptr) {
5777+
///
5778+
/// The function should return the body statement and a flag indicating
5779+
/// whether that body is already type-checked.
5780+
void setBodySynthesizer(
5781+
std::pair<BraceStmt *, bool> (* fn)(AbstractFunctionDecl *, void *),
5782+
void *context = nullptr) {
57895783
assert(getBodyKind() == BodyKind::None);
57905784
Synthesizer = {fn, context};
57915785
setBodyKind(BodyKind::Synthesize);

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ SourceRange AbstractFunctionDeclScope::getChildlessSourceRange() const {
301301
assert(r.End.isValid());
302302
return r;
303303
}
304-
return decl->getBody()->getSourceRange();
304+
return decl->getBodySourceRange();
305305
}
306306

307307
SourceRange AbstractFunctionParamsScope::getChildlessSourceRange() const {

lib/AST/Decl.cpp

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6237,17 +6237,51 @@ bool AbstractFunctionDecl::argumentNameIsAPIByDefault() const {
62376237
return false;
62386238
}
62396239

6240+
BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
6241+
switch (getBodyKind()) {
6242+
case BodyKind::Deserialized:
6243+
case BodyKind::MemberwiseInitializer:
6244+
case BodyKind::None:
6245+
case BodyKind::Skipped:
6246+
return nullptr;
6247+
6248+
case BodyKind::Parsed:
6249+
case BodyKind::TypeChecked:
6250+
return Body;
6251+
6252+
case BodyKind::Unparsed:
6253+
// FIXME: Go parse now!
6254+
return nullptr;
6255+
6256+
case BodyKind::Synthesize: {
6257+
if (!canSynthesize)
6258+
return nullptr;
6259+
6260+
const_cast<AbstractFunctionDecl *>(this)->setBodyKind(BodyKind::None);
6261+
BraceStmt *body;
6262+
bool isTypeChecked;
6263+
6264+
auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
6265+
std::tie(body, isTypeChecked) = (Synthesizer.Fn)(
6266+
mutableThis, Synthesizer.Context);
6267+
mutableThis->setBody(
6268+
body, isTypeChecked ? BodyKind::TypeChecked : BodyKind::Parsed);
6269+
return body;
6270+
}
6271+
}
6272+
}
6273+
62406274
SourceRange AbstractFunctionDecl::getBodySourceRange() const {
62416275
switch (getBodyKind()) {
62426276
case BodyKind::None:
62436277
case BodyKind::MemberwiseInitializer:
62446278
case BodyKind::Deserialized:
6279+
case BodyKind::Synthesize:
62456280
return SourceRange();
62466281

62476282
case BodyKind::Parsed:
6248-
case BodyKind::Synthesize:
62496283
case BodyKind::TypeChecked:
6250-
if (auto body = getBody())
6284+
if (auto body = getBody(/*canSynthesize=*/false))
62516285
return body->getSourceRange();
62526286

62536287
return SourceRange();
@@ -6969,9 +7003,9 @@ SourceRange FuncDecl::getSourceRange() const {
69697003
getBodyKind() == BodyKind::Skipped)
69707004
return { StartLoc, BodyRange.End };
69717005

6972-
if (auto *B = getBody(/*canSynthesize=*/false)) {
6973-
if (!B->isImplicit())
6974-
return { StartLoc, B->getEndLoc() };
7006+
SourceLoc RBraceLoc = getBodySourceRange().End;
7007+
if (RBraceLoc.isValid()) {
7008+
return { StartLoc, RBraceLoc };
69757009
}
69767010

69777011
if (isa<AccessorDecl>(this))
@@ -7070,13 +7104,7 @@ SourceRange ConstructorDecl::getSourceRange() const {
70707104
if (isImplicit())
70717105
return getConstructorLoc();
70727106

7073-
if (getBodyKind() == BodyKind::Unparsed ||
7074-
getBodyKind() == BodyKind::Skipped)
7075-
return { getConstructorLoc(), BodyRange.End };
7076-
7077-
SourceLoc End;
7078-
if (auto body = getBody())
7079-
End = body->getEndLoc();
7107+
SourceLoc End = getBodySourceRange().End;
70807108
if (End.isInvalid())
70817109
End = getGenericTrailingWhereClauseSourceRange().End;
70827110
if (End.isInvalid())
@@ -7284,14 +7312,12 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
72847312
}
72857313

72867314
SourceRange DestructorDecl::getSourceRange() const {
7287-
if (getBodyKind() == BodyKind::Unparsed ||
7288-
getBodyKind() == BodyKind::Skipped)
7289-
return { getDestructorLoc(), BodyRange.End };
7290-
7291-
if (getBodyKind() == BodyKind::None)
7292-
return getDestructorLoc();
7315+
SourceLoc End = getBodySourceRange().End;
7316+
if (End.isInvalid()) {
7317+
End = getDestructorLoc();
7318+
}
72937319

7294-
return { getDestructorLoc(), getBody()->getEndLoc() };
7320+
return { getDestructorLoc(), End };
72957321
}
72967322

72977323
StringRef swift::getAssociativitySpelling(Associativity value) {

0 commit comments

Comments
 (0)