Skip to content

Commit be60ff0

Browse files
authored
Merge pull request #42299 from ktoso/pick-cache-checking-dist-func
🍒[5.7][Distributed] Cache checking distributed func
2 parents f4564c2 + 6225b96 commit be60ff0

File tree

6 files changed

+60
-25
lines changed

6 files changed

+60
-25
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,33 @@ class GetDistributedActorImplicitCodableRequest :
10831083
bool isCached() const { return true; }
10841084
};
10851085

1086+
/// Check a distributed function declaration and cache if it was valid or not.
1087+
///
1088+
/// This is used because we not only type-check to emit errors, but also use
1089+
/// the information to potentially avoid emitting the distributed thunk for
1090+
/// methods which are invalid (e.g. their parameters dont conform to
1091+
/// SerializationRequirement), as otherwise we'd be causing errors in synthesized
1092+
/// code which looks very confusing to end-users.
1093+
///
1094+
class CheckDistributedFunctionRequest :
1095+
public SimpleRequest<CheckDistributedFunctionRequest,
1096+
bool(AbstractFunctionDecl *),
1097+
RequestFlags::Cached> {
1098+
public:
1099+
using SimpleRequest::SimpleRequest;
1100+
1101+
private:
1102+
friend SimpleRequest;
1103+
1104+
/// \returns \c true if there was a problem with the function declaration,
1105+
/// \c false otherwise.
1106+
bool evaluate(Evaluator &evaluator, AbstractFunctionDecl *) const;
1107+
1108+
public:
1109+
// Caching
1110+
bool isCached() const { return true; }
1111+
};
1112+
10861113
/// Obtain the 'remoteCall' function of a 'DistributedActorSystem'.
10871114
class GetDistributedActorSystemRemoteCallFunctionRequest :
10881115
public SimpleRequest<GetDistributedActorSystemRemoteCallFunctionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ SWIFT_REQUEST(TypeChecker, IsActorRequest, bool(NominalTypeDecl *),
110110
SWIFT_REQUEST(TypeChecker, IsDefaultActorRequest,
111111
bool(ClassDecl *, ModuleDecl *, ResilienceExpansion),
112112
Cached, NoLocationInfo)
113+
SWIFT_REQUEST(TypeChecker, CheckDistributedFunctionRequest,
114+
bool(AbstractFunctionDecl *),
115+
Cached, NoLocationInfo)
113116
SWIFT_REQUEST(TypeChecker, IsDistributedActorRequest, bool(NominalTypeDecl *),
114117
Cached, NoLocationInfo)
115118
SWIFT_REQUEST(TypeChecker, GetDistributedActorImplicitCodableRequest,

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -696,10 +696,12 @@ FuncDecl *GetDistributedThunkRequest::evaluate(
696696
return nullptr;
697697
}
698698

699-
// Force type-checking the original function, so we can avoid synthesizing
700-
// the thunks (which would have many of the same errors, if they are caused
701-
// by a bad source function signature, e.g. missing conformances etc).
702-
if (distributedTarget->getInterfaceType()->hasError()) {
699+
// If the target function signature has errors, or if it is illegal in other
700+
// ways, such as e.g. parameters not conforming to SerializationRequirement,
701+
// we must avoid synthesis of the thunk because it'd also have errors,
702+
// giving an ugly user experience (errors in implicit code).
703+
if (distributedTarget->getInterfaceType()->hasError() ||
704+
checkDistributedFunction(distributedTarget)) {
703705
return nullptr;
704706
}
705707

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3256,7 +3256,7 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
32563256
}
32573257
if (decl->getAttrs().hasAttribute<DistributedActorAttr>()) {
32583258
if (auto func = dyn_cast<FuncDecl>(decl)) {
3259-
checkDistributedFunction(func, /*diagnose=*/true);
3259+
checkDistributedFunction(func);
32603260
}
32613261
}
32623262
}

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "TypeCheckConcurrency.h"
1717
#include "TypeCheckDistributed.h"
1818
#include "TypeChecker.h"
19-
#include "TypeCheckType.h"
2019
#include "swift/Strings.h"
2120
#include "swift/AST/ASTWalker.h"
2221
#include "swift/AST/Initializer.h"
@@ -434,11 +433,17 @@ static bool checkDistributedTargetResultType(
434433

435434
/// Check whether the function is a proper distributed function
436435
///
437-
/// \param diagnose Whether to emit a diagnostic when a problem is encountered.
438-
///
439436
/// \returns \c true if there was a problem with adding the attribute, \c false
440437
/// otherwise.
441-
bool swift::checkDistributedFunction(FuncDecl *func, bool diagnose) {
438+
bool swift::checkDistributedFunction(AbstractFunctionDecl *func) {
439+
auto &C = func->getASTContext();
440+
return evaluateOrDefault(C.evaluator,
441+
CheckDistributedFunctionRequest{func},
442+
false); // no error if cycle
443+
}
444+
445+
bool CheckDistributedFunctionRequest::evaluate(
446+
Evaluator &evaluator, AbstractFunctionDecl *func) const {
442447
assert(func->isDistributed());
443448

444449
auto &C = func->getASTContext();
@@ -456,9 +461,8 @@ bool swift::checkDistributedFunction(FuncDecl *func, bool diagnose) {
456461
serializationRequirements = extractDistributedSerializationRequirements(
457462
C, extension->getGenericRequirements());
458463
} else if (auto actor = dyn_cast<ClassDecl>(DC)) {
459-
auto systemProp = actor->getDistributedActorSystemProperty();
460464
serializationRequirements = getDistributedSerializationRequirementProtocols(
461-
systemProp->getInterfaceType()->getAnyNominal(),
465+
getDistributedActorSystemType(actor)->getAnyNominal(),
462466
C.getProtocol(KnownProtocolKind::DistributedActorSystem));
463467
} else {
464468
llvm_unreachable("Cannot handle types other than extensions and actor "
@@ -476,18 +480,16 @@ bool swift::checkDistributedFunction(FuncDecl *func, bool diagnose) {
476480

477481
for (auto req : serializationRequirements) {
478482
if (TypeChecker::conformsToProtocol(paramTy, req, module).isInvalid()) {
479-
if (diagnose) {
480-
auto diag = func->diagnose(
481-
diag::distributed_actor_func_param_not_codable,
482-
param->getArgumentName().str(), param->getInterfaceType(),
483-
func->getDescriptiveKind(),
484-
serializationRequirementIsCodable ? "Codable"
485-
: req->getNameStr());
486-
487-
if (auto paramNominalTy = paramTy->getAnyNominal()) {
488-
addCodableFixIt(paramNominalTy, diag);
489-
} // else, no nominal type to suggest the fixit for, e.g. a closure
490-
}
483+
auto diag = func->diagnose(
484+
diag::distributed_actor_func_param_not_codable,
485+
param->getArgumentName().str(), param->getInterfaceType(),
486+
func->getDescriptiveKind(),
487+
serializationRequirementIsCodable ? "Codable"
488+
: req->getNameStr());
489+
490+
if (auto paramNominalTy = paramTy->getAnyNominal()) {
491+
addCodableFixIt(paramNominalTy, diag);
492+
} // else, no nominal type to suggest the fixit for, e.g. a closure
491493
return true;
492494
}
493495
}
@@ -513,7 +515,8 @@ bool swift::checkDistributedFunction(FuncDecl *func, bool diagnose) {
513515
}
514516

515517
// --- Result type must be either void or a codable type
516-
if (checkDistributedTargetResultType(module, func, serializationRequirements, diagnose)) {
518+
if (checkDistributedTargetResultType(module, func, serializationRequirements,
519+
/*diagnose=*/true)) {
517520
return true;
518521
}
519522

lib/Sema/TypeCheckDistributed.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ bool checkDistributedActorSystemAdHocProtocolRequirements(
5151
bool diagnose);
5252

5353
/// Typecheck a distributed method declaration
54-
bool checkDistributedFunction(FuncDecl *decl, bool diagnose);
54+
bool checkDistributedFunction(AbstractFunctionDecl *decl);
5555

5656
/// Typecheck a distributed computed (get-only) property declaration.
5757
/// They are effectively checked the same way as argument-less methods.

0 commit comments

Comments
 (0)