Skip to content

Commit 1579673

Browse files
committed
[Sema] Descriptor for argument of PreCheckFunctionBuilderRequest
1 parent 7a5f525 commit 1579673

File tree

3 files changed

+52
-20
lines changed

3 files changed

+52
-20
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,6 +1823,45 @@ class ValueWitnessRequest
18231823
void cacheResult(Witness value) const;
18241824
};
18251825

1826+
struct PreCheckFunctionBuilderDescriptor {
1827+
AnyFunctionRef Fn;
1828+
1829+
private:
1830+
// NOTE: Since source tooling (e.g. code completion) might replace the body,
1831+
// we need to take the body into account to calculate 'hash_value' and '=='.
1832+
// Also, we cannot 'getBody()' inside 'hash_value' and '==' because it invokes
1833+
// another request (even if it's cached).
1834+
BraceStmt *Body;
1835+
1836+
public:
1837+
PreCheckFunctionBuilderDescriptor(AnyFunctionRef Fn)
1838+
: Fn(Fn), Body(Fn.getBody()) {}
1839+
1840+
friend llvm::hash_code
1841+
hash_value(const PreCheckFunctionBuilderDescriptor &owner) {
1842+
return llvm::hash_combine(owner.Fn, owner.Body);
1843+
}
1844+
1845+
friend bool operator==(const PreCheckFunctionBuilderDescriptor &lhs,
1846+
const PreCheckFunctionBuilderDescriptor &rhs) {
1847+
return lhs.Fn == rhs.Fn && lhs.Body == rhs.Body;
1848+
}
1849+
1850+
friend bool operator!=(const PreCheckFunctionBuilderDescriptor &lhs,
1851+
const PreCheckFunctionBuilderDescriptor &rhs) {
1852+
return !(lhs == rhs);
1853+
}
1854+
1855+
friend SourceLoc extractNearestSourceLoc(PreCheckFunctionBuilderDescriptor d) {
1856+
return extractNearestSourceLoc(d.Fn);
1857+
}
1858+
1859+
friend void simple_display(llvm::raw_ostream &out,
1860+
const PreCheckFunctionBuilderDescriptor &d) {
1861+
simple_display(out, d.Fn);
1862+
}
1863+
};
1864+
18261865
enum class FunctionBuilderBodyPreCheck : uint8_t {
18271866
/// There were no problems pre-checking the closure.
18281867
Okay,
@@ -1836,8 +1875,8 @@ enum class FunctionBuilderBodyPreCheck : uint8_t {
18361875

18371876
class PreCheckFunctionBuilderRequest
18381877
: public SimpleRequest<PreCheckFunctionBuilderRequest,
1839-
FunctionBuilderBodyPreCheck(AnyFunctionRef,
1840-
BraceStmt *),
1878+
FunctionBuilderBodyPreCheck(
1879+
PreCheckFunctionBuilderDescriptor),
18411880
RequestFlags::Cached> {
18421881
public:
18431882
using SimpleRequest::SimpleRequest;
@@ -1846,8 +1885,8 @@ class PreCheckFunctionBuilderRequest
18461885
friend SimpleRequest;
18471886

18481887
// Evaluation.
1849-
FunctionBuilderBodyPreCheck evaluate(Evaluator &evaluator, AnyFunctionRef fn,
1850-
BraceStmt *body) const;
1888+
FunctionBuilderBodyPreCheck
1889+
evaluate(Evaluator &evaluator, PreCheckFunctionBuilderDescriptor owner) const;
18511890

18521891
public:
18531892
// Separate caching.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ SWIFT_REQUEST(TypeChecker, HasUserDefinedDesignatedInitRequest,
231231
SWIFT_REQUEST(TypeChecker, HasMemberwiseInitRequest,
232232
bool(StructDecl *), Cached, NoLocationInfo)
233233
SWIFT_REQUEST(TypeChecker, PreCheckFunctionBuilderRequest,
234-
FunctionBuilderClosurePreCheck(AnyFunctionRef, BraceStmt *),
234+
FunctionBuilderClosurePreCheck(PreCheckFunctionBuilderDescriptor),
235235
Cached, NoLocationInfo)
236236
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
237237
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),

lib/Sema/BuilderTransform.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,7 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
14641464
// If we encountered an error or there was an explicit result type,
14651465
// bail out and report that to the caller.
14661466
auto &ctx = func->getASTContext();
1467-
auto request = PreCheckFunctionBuilderRequest{func, func->getBody()};
1467+
auto request = PreCheckFunctionBuilderRequest{AnyFunctionRef(func)};
14681468
switch (evaluateOrDefault(
14691469
ctx.evaluator, request, FunctionBuilderBodyPreCheck::Error)) {
14701470
case FunctionBuilderBodyPreCheck::Okay:
@@ -1592,7 +1592,7 @@ ConstraintSystem::matchFunctionBuilder(
15921592

15931593
// Pre-check the body: pre-check any expressions in it and look
15941594
// for return statements.
1595-
auto request = PreCheckFunctionBuilderRequest{fn, fn.getBody()};
1595+
auto request = PreCheckFunctionBuilderRequest{fn};
15961596
switch (evaluateOrDefault(getASTContext().evaluator, request,
15971597
FunctionBuilderBodyPreCheck::Error)) {
15981598
case FunctionBuilderBodyPreCheck::Okay:
@@ -1712,11 +1712,11 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17121712
if (HasError)
17131713
return FunctionBuilderBodyPreCheck::Error;
17141714

1715+
assert(oldBody == newBody && "pre-check walk wasn't in-place?");
1716+
17151717
if (hasReturnStmt())
17161718
return FunctionBuilderBodyPreCheck::HasReturnStmt;
17171719

1718-
assert(oldBody == newBody && "pre-check walk wasn't in-place?");
1719-
17201720
return FunctionBuilderBodyPreCheck::Okay;
17211721
}
17221722

@@ -1754,23 +1754,16 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17541754

17551755
}
17561756

1757-
FunctionBuilderBodyPreCheck
1758-
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval, AnyFunctionRef fn,
1759-
BraceStmt *body) const {
1760-
// NOTE: 'body' is passed only for the request evaluater caching key.
1761-
// Since source tooling (e.g. code completion) might replace the body,
1762-
// the function alone is not sufficient for the key.
1763-
assert(fn.getBody() == body &&
1764-
"body must be the current body of the function");
1765-
1757+
FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate(
1758+
Evaluator &evaluator, PreCheckFunctionBuilderDescriptor owner) const {
17661759
// We don't want to do the precheck if it will already have happened in
17671760
// the enclosing expression.
17681761
bool skipPrecheck = false;
17691762
if (auto closure = dyn_cast_or_null<ClosureExpr>(
1770-
fn.getAbstractClosureExpr()))
1763+
owner.Fn.getAbstractClosureExpr()))
17711764
skipPrecheck = shouldTypeCheckInEnclosingExpression(closure);
17721765

1773-
return PreCheckFunctionBuilderApplication(fn, false).run();
1766+
return PreCheckFunctionBuilderApplication(owner.Fn, false).run();
17741767
}
17751768

17761769
std::vector<ReturnStmt *> TypeChecker::findReturnStatements(AnyFunctionRef fn) {

0 commit comments

Comments
 (0)