Skip to content

Commit f2a1abc

Browse files
committed
[NFC] Refactor Side-Effecting Requests to be Explicitly so
Introduce evaluator::SideEffect, the type of a request that performs some operation solely to execute its side effects. Thankfully, there are precious few requests that need to use this type in practice, but it's good to call them out explicitly so we can get around to making them behave much more functionally in the future.
1 parent 8c61335 commit f2a1abc

13 files changed

+74
-43
lines changed

include/swift/AST/SILOptimizerRequests.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ llvm::hash_code hash_value(const SILPipelineExecutionDescriptor &desc);
5050
/// Executes a SIL pipeline plan on a SIL module.
5151
class ExecuteSILPipelineRequest
5252
: public SimpleRequest<ExecuteSILPipelineRequest,
53-
bool(SILPipelineExecutionDescriptor),
53+
evaluator::SideEffect(SILPipelineExecutionDescriptor),
5454
CacheKind::Uncached> {
5555
public:
5656
using SimpleRequest::SimpleRequest;
@@ -59,8 +59,8 @@ class ExecuteSILPipelineRequest
5959
friend SimpleRequest;
6060

6161
// Evaluation.
62-
llvm::Expected<bool> evaluate(Evaluator &evaluator,
63-
SILPipelineExecutionDescriptor desc) const;
62+
llvm::Expected<evaluator::SideEffect>
63+
evaluate(Evaluator &evaluator, SILPipelineExecutionDescriptor desc) const;
6464
};
6565

6666
void simple_display(llvm::raw_ostream &out,

include/swift/AST/SILOptimizerTypeIDZone.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
SWIFT_REQUEST(SILOptimizer, ExecuteSILPipelineRequest,
18-
bool(SILPipelineExecutionDescriptor), Uncached, NoLocationInfo)
18+
evaluator::SideEffect(SILPipelineExecutionDescriptor),
19+
Uncached, NoLocationInfo)

include/swift/AST/TypeCheckRequests.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ class OperatorPrecedenceGroupRequest
12471247
/// Computes the raw values for an enum type.
12481248
class EnumRawValuesRequest :
12491249
public SimpleRequest<EnumRawValuesRequest,
1250-
bool (EnumDecl *, TypeResolutionStage),
1250+
evaluator::SideEffect (EnumDecl *, TypeResolutionStage),
12511251
CacheKind::SeparatelyCached> {
12521252
public:
12531253
using SimpleRequest::SimpleRequest;
@@ -1256,7 +1256,7 @@ class EnumRawValuesRequest :
12561256
friend SimpleRequest;
12571257

12581258
// Evaluation.
1259-
llvm::Expected<bool>
1259+
llvm::Expected<evaluator::SideEffect>
12601260
evaluate(Evaluator &evaluator, EnumDecl *ED, TypeResolutionStage stage) const;
12611261

12621262
public:
@@ -1266,8 +1266,8 @@ class EnumRawValuesRequest :
12661266

12671267
// Separate caching.
12681268
bool isCached() const;
1269-
Optional<bool> getCachedResult() const;
1270-
void cacheResult(bool value) const;
1269+
Optional<evaluator::SideEffect> getCachedResult() const;
1270+
void cacheResult(evaluator::SideEffect value) const;
12711271
};
12721272

12731273
/// Determines if an override is ABI compatible with its base method.
@@ -1718,7 +1718,7 @@ enum class ImplicitMemberAction : uint8_t {
17181718

17191719
class ResolveImplicitMemberRequest
17201720
: public SimpleRequest<ResolveImplicitMemberRequest,
1721-
bool(NominalTypeDecl *, ImplicitMemberAction),
1721+
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),
17221722
CacheKind::Uncached> {
17231723
public:
17241724
using SimpleRequest::SimpleRequest;
@@ -1727,8 +1727,9 @@ class ResolveImplicitMemberRequest
17271727
friend SimpleRequest;
17281728

17291729
// Evaluation.
1730-
llvm::Expected<bool> evaluate(Evaluator &evaluator, NominalTypeDecl *NTD,
1731-
ImplicitMemberAction action) const;
1730+
llvm::Expected<evaluator::SideEffect>
1731+
evaluate(Evaluator &evaluator, NominalTypeDecl *NTD,
1732+
ImplicitMemberAction action) const;
17321733

17331734
public:
17341735
// Separate caching.
@@ -1984,21 +1985,23 @@ class DynamicallyReplacedDeclRequest
19841985

19851986
class TypeCheckSourceFileRequest :
19861987
public SimpleRequest<TypeCheckSourceFileRequest,
1987-
bool (SourceFile *), CacheKind::SeparatelyCached> {
1988+
evaluator::SideEffect (SourceFile *),
1989+
CacheKind::SeparatelyCached> {
19881990
public:
19891991
using SimpleRequest::SimpleRequest;
19901992

19911993
private:
19921994
friend SimpleRequest;
19931995

19941996
// Evaluation.
1995-
llvm::Expected<bool> evaluate(Evaluator &evaluator, SourceFile *SF) const;
1997+
llvm::Expected<evaluator::SideEffect>
1998+
evaluate(Evaluator &evaluator, SourceFile *SF) const;
19961999

19972000
public:
19982001
// Separate caching.
19992002
bool isCached() const { return true; }
2000-
Optional<bool> getCachedResult() const;
2001-
void cacheResult(bool result) const;
2003+
Optional<evaluator::SideEffect> getCachedResult() const;
2004+
void cacheResult(evaluator::SideEffect) const;
20022005
};
20032006

20042007
/// Computes whether the specified type or a super-class/super-protocol has the

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ SWIFT_REQUEST(TypeChecker, DynamicallyReplacedDeclRequest,
5555
SWIFT_REQUEST(TypeChecker, EmittedMembersRequest, DeclRange(ClassDecl *),
5656
SeparatelyCached, NoLocationInfo)
5757
SWIFT_REQUEST(TypeChecker, EnumRawValuesRequest,
58-
bool (EnumDecl *, TypeResolutionStage), SeparatelyCached,
59-
NoLocationInfo)
58+
evaluator::SideEffect (EnumDecl *, TypeResolutionStage),
59+
SeparatelyCached, NoLocationInfo)
6060
SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
6161
Type(EnumDecl *, TypeResolutionStage), SeparatelyCached,
6262
NoLocationInfo)
@@ -182,7 +182,8 @@ SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest,
182182
AccessorDecl *(AbstractStorageDecl *, AccessorKind),
183183
SeparatelyCached, NoLocationInfo)
184184
SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyUntilRequest,
185-
bool(AbstractFunctionDecl *, SourceLoc), Cached, NoLocationInfo)
185+
bool(AbstractFunctionDecl *, SourceLoc),
186+
Cached, NoLocationInfo)
186187
SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *),
187188
SeparatelyCached, NoLocationInfo)
188189
SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *),
@@ -207,8 +208,8 @@ SWIFT_REQUEST(TypeChecker, PreCheckFunctionBuilderRequest,
207208
FunctionBuilderClosurePreCheck(AnyFunctionRef),
208209
Cached, NoLocationInfo)
209210
SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
210-
bool(NominalTypeDecl *, ImplicitMemberAction), Uncached,
211-
NoLocationInfo)
211+
evaluator::SideEffect(NominalTypeDecl *, ImplicitMemberAction),
212+
Uncached, NoLocationInfo)
212213
SWIFT_REQUEST(TypeChecker, SPIGroupsRequest,
213214
llvm::ArrayRef<Identifier>(Decl *),
214215
Cached, NoLocationInfo)

include/swift/Basic/CTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ SWIFT_TYPEID_NAMED(void, Void)
3535
SWIFT_TYPEID_NAMED(std::string, String)
3636

3737
// C++ standard library types.
38+
SWIFT_TYPEID_NAMED(evaluator::SideEffect, SideEffect)
3839
SWIFT_TYPEID_TEMPLATE1_NAMED(std::vector, Vector, typename T, T)
3940
SWIFT_TYPEID_TEMPLATE1_NAMED(std::unique_ptr, UniquePtr, typename T, T)
4041

include/swift/Basic/TypeID.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,29 @@ constexpr uint64_t formTypeID(uint8_t zone, uint8_t type) {
6666
return (uint64_t(zone) << 8) | uint64_t(type);
6767
}
6868

69+
namespace evaluator {
70+
/// The return type of requests that execute side effects.
71+
///
72+
/// In general, it is not appropriate to use the request evaluator framework to
73+
/// execute a request for the sake of its side effects. However, there are
74+
/// operations we would currently like to be requests because it makes modelling
75+
/// some aspect of their implementation particularly nice. For example, an
76+
/// operation that emits diagnostics to run some checking code in a primary
77+
/// file may be desirable to requestify because it should be run only once per
78+
/// declaration, but it has no coherent return value. Another category of
79+
/// side-effecting requests are those that adapt existing parts of the compiler that
80+
/// do not yet behave in a "functional" manner to have a functional interface. Consider
81+
/// the request to run the SIL Optimizer. In theory, it should be a request that takes in
82+
/// a SILModule and returns a SILModule. In practice, it is a request that executes
83+
/// effects against a SILModule.
84+
///
85+
/// To make these requests stand out - partially in the hope we can return and
86+
/// refactor them to behave in a more well-structured manner, partially because
87+
/// they cannot return \c void or we will get template substitution failures - we
88+
/// annotate them as computing an \c evaluator::SideEffect.
89+
using SideEffect = std::tuple<>;
90+
}
91+
6992
// Define the C type zone (zone 0).
7093
#define SWIFT_TYPEID_ZONE C
7194
#define SWIFT_TYPEID_HEADER "swift/Basic/CTypeIDZone.def"

lib/AST/Decl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4125,7 +4125,7 @@ void NominalTypeDecl::synthesizeSemanticMembersIfNeeded(DeclName member) {
41254125

41264126
if (auto actionToTake = action) {
41274127
(void)evaluateOrDefault(Context.evaluator,
4128-
ResolveImplicitMemberRequest{this, actionToTake.getValue()}, false);
4128+
ResolveImplicitMemberRequest{this, actionToTake.getValue()}, {});
41294129
}
41304130
}
41314131

@@ -7486,7 +7486,7 @@ LiteralExpr *EnumElementDecl::getRawValueExpr() const {
74867486
(void)evaluateOrDefault(
74877487
getASTContext().evaluator,
74887488
EnumRawValuesRequest{getParentEnum(), TypeResolutionStage::Interface},
7489-
true);
7489+
{});
74907490
return RawValueExpr;
74917491
}
74927492

@@ -7496,7 +7496,7 @@ LiteralExpr *EnumElementDecl::getStructuralRawValueExpr() const {
74967496
(void)evaluateOrDefault(
74977497
getASTContext().evaluator,
74987498
EnumRawValuesRequest{getParentEnum(), TypeResolutionStage::Structural},
7499-
true);
7499+
{});
75007500
return RawValueExpr;
75017501
}
75027502

lib/AST/TypeCheckRequests.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -863,14 +863,14 @@ bool EnumRawValuesRequest::isCached() const {
863863
return std::get<1>(getStorage()) == TypeResolutionStage::Interface;
864864
}
865865

866-
Optional<bool> EnumRawValuesRequest::getCachedResult() const {
866+
Optional<evaluator::SideEffect> EnumRawValuesRequest::getCachedResult() const {
867867
auto *ED = std::get<0>(getStorage());
868868
if (ED->LazySemanticInfo.hasCheckedRawValues())
869-
return true;
869+
return std::make_tuple<>();
870870
return None;
871871
}
872872

873-
void EnumRawValuesRequest::cacheResult(bool) const {
873+
void EnumRawValuesRequest::cacheResult(evaluator::SideEffect) const {
874874
auto *ED = std::get<0>(getStorage());
875875
auto flags = ED->LazySemanticInfo.RawTypeAndFlags.getInt() |
876876
EnumDecl::HasFixedRawValues |
@@ -1268,15 +1268,16 @@ void DifferentiableAttributeTypeCheckRequest::cacheResult(
12681268
// TypeCheckSourceFileRequest computation.
12691269
//----------------------------------------------------------------------------//
12701270

1271-
Optional<bool> TypeCheckSourceFileRequest::getCachedResult() const {
1271+
Optional<evaluator::SideEffect>
1272+
TypeCheckSourceFileRequest::getCachedResult() const {
12721273
auto *SF = std::get<0>(getStorage());
12731274
if (SF->ASTStage == SourceFile::TypeChecked)
1274-
return true;
1275+
return std::make_tuple<>();
12751276

12761277
return None;
12771278
}
12781279

1279-
void TypeCheckSourceFileRequest::cacheResult(bool result) const {
1280+
void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const {
12801281
auto *SF = std::get<0>(getStorage());
12811282

12821283
// Verify that we've checked types correctly.

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,12 @@ class PassManagerDeserializationNotificationHandler final
276276

277277
} // end anonymous namespace
278278

279-
llvm::Expected<bool> ExecuteSILPipelineRequest::evaluate(
279+
llvm::Expected<evaluator::SideEffect>
280+
ExecuteSILPipelineRequest::evaluate(
280281
Evaluator &evaluator, SILPipelineExecutionDescriptor desc) const {
281282
SILPassManager PM(desc.SM, desc.IsMandatory, desc.IRMod);
282283
PM.executePassPipelinePlan(desc.Plan);
283-
return false;
284+
return std::make_tuple<>();
284285
}
285286

286287
void swift::executePassPipelinePlan(SILModule *SM,

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
10851085
(void)decl->getDefaultInitializer();
10861086
}
10871087

1088-
llvm::Expected<bool>
1088+
llvm::Expected<evaluator::SideEffect>
10891089
ResolveImplicitMemberRequest::evaluate(Evaluator &evaluator,
10901090
NominalTypeDecl *target,
10911091
ImplicitMemberAction action) const {
@@ -1162,7 +1162,7 @@ ResolveImplicitMemberRequest::evaluate(Evaluator &evaluator,
11621162
}
11631163
break;
11641164
}
1165-
return true;
1165+
return std::make_tuple<>();
11661166
}
11671167

11681168
llvm::Expected<bool>

0 commit comments

Comments
 (0)