Skip to content

Commit 994edab

Browse files
authored
Merge pull request #33013 from rintaro/sema-precheckfunctionbuilder-descriptor
[Sema] Descriptor for argument of PreCheckFunctionBuilderRequest
2 parents c120ff8 + 1579673 commit 994edab

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
@@ -1461,7 +1461,7 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
14611461
// If we encountered an error or there was an explicit result type,
14621462
// bail out and report that to the caller.
14631463
auto &ctx = func->getASTContext();
1464-
auto request = PreCheckFunctionBuilderRequest{func, func->getBody()};
1464+
auto request = PreCheckFunctionBuilderRequest{AnyFunctionRef(func)};
14651465
switch (evaluateOrDefault(
14661466
ctx.evaluator, request, FunctionBuilderBodyPreCheck::Error)) {
14671467
case FunctionBuilderBodyPreCheck::Okay:
@@ -1589,7 +1589,7 @@ ConstraintSystem::matchFunctionBuilder(
15891589

15901590
// Pre-check the body: pre-check any expressions in it and look
15911591
// for return statements.
1592-
auto request = PreCheckFunctionBuilderRequest{fn, fn.getBody()};
1592+
auto request = PreCheckFunctionBuilderRequest{fn};
15931593
switch (evaluateOrDefault(getASTContext().evaluator, request,
15941594
FunctionBuilderBodyPreCheck::Error)) {
15951595
case FunctionBuilderBodyPreCheck::Okay:
@@ -1693,11 +1693,11 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
16931693
if (HasError)
16941694
return FunctionBuilderBodyPreCheck::Error;
16951695

1696+
assert(oldBody == newBody && "pre-check walk wasn't in-place?");
1697+
16961698
if (hasReturnStmt())
16971699
return FunctionBuilderBodyPreCheck::HasReturnStmt;
16981700

1699-
assert(oldBody == newBody && "pre-check walk wasn't in-place?");
1700-
17011701
return FunctionBuilderBodyPreCheck::Okay;
17021702
}
17031703

@@ -1735,23 +1735,16 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17351735

17361736
}
17371737

1738-
FunctionBuilderBodyPreCheck
1739-
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval, AnyFunctionRef fn,
1740-
BraceStmt *body) const {
1741-
// NOTE: 'body' is passed only for the request evaluater caching key.
1742-
// Since source tooling (e.g. code completion) might replace the body,
1743-
// the function alone is not sufficient for the key.
1744-
assert(fn.getBody() == body &&
1745-
"body must be the current body of the function");
1746-
1738+
FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate(
1739+
Evaluator &evaluator, PreCheckFunctionBuilderDescriptor owner) const {
17471740
// We don't want to do the precheck if it will already have happened in
17481741
// the enclosing expression.
17491742
bool skipPrecheck = false;
17501743
if (auto closure = dyn_cast_or_null<ClosureExpr>(
1751-
fn.getAbstractClosureExpr()))
1744+
owner.Fn.getAbstractClosureExpr()))
17521745
skipPrecheck = shouldTypeCheckInEnclosingExpression(closure);
17531746

1754-
return PreCheckFunctionBuilderApplication(fn, false).run();
1747+
return PreCheckFunctionBuilderApplication(owner.Fn, false).run();
17551748
}
17561749

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

0 commit comments

Comments
 (0)