Skip to content

Commit 82a0067

Browse files
committed
Merge pull request #166 from przybylski/betterDefer
Make c++ defer looks like a swift one
2 parents d7eba16 + 0e5c7dd commit 82a0067

File tree

6 files changed

+30
-23
lines changed

6 files changed

+30
-23
lines changed

include/swift/Basic/Defer.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,44 @@
1818
#ifndef __SWIFT_DEFER_H
1919
#define __SWIFT_DEFER_H
2020

21+
#include <type_traits>
22+
2123
namespace swift {
2224
template <typename F>
2325
class DoAtScopeExit {
2426
F &Fn;
25-
DoAtScopeExit(DoAtScopeExit&) = delete;
2627
void operator=(DoAtScopeExit&) = delete;
2728
public:
2829
DoAtScopeExit(F &Fn) : Fn(Fn){}
2930
~DoAtScopeExit() {
3031
Fn();
3132
}
3233
};
34+
35+
namespace detail {
36+
struct DeferTask {};
37+
template<typename F>
38+
DoAtScopeExit<typename std::decay<F>::type> operator+(DeferTask, F&& fn) {
39+
return DoAtScopeExit<typename std::decay<F>::type>(fn);
40+
}
41+
}
3342
}
3443

44+
3545
#define DEFER_CONCAT_IMPL(x, y) x##y
3646
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
3747

3848

3949
/// This macro is used to register a function / lambda to be run on exit from a
4050
/// scope. Its typical use looks like:
4151
///
42-
/// defer([&]{
52+
/// defer {
4353
/// stuff
44-
/// })
54+
/// };
4555
///
46-
#define defer(x) \
47-
auto DEFER_MACRO_CONCAT(defer_func, __LINE__) = (x); \
48-
swift::DoAtScopeExit<decltype(DEFER_MACRO_CONCAT(defer_func, __LINE__))> \
49-
DEFER_MACRO_CONCAT(defer_local, __LINE__)\
50-
(DEFER_MACRO_CONCAT(defer_func, __LINE__));
56+
#define defer \
57+
auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) = \
58+
::swift::detail::DeferTask() + [&]()
5159

5260
#endif
5361

54-

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3643,7 +3643,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
36433643

36443644
// No matter what error path we take, make sure the
36453645
// PatternBindingDecl/TopLevel code block are added.
3646-
defer([&]{
3646+
defer {
36473647
// If we didn't parse any patterns, don't create the pattern binding decl.
36483648
if (PBDEntries.empty())
36493649
return;
@@ -3683,7 +3683,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
36833683
// specific spot to get it in before any accessors, which SILGen seems to
36843684
// want.
36853685
Decls.insert(Decls.begin()+NumDeclsInResult, PBD);
3686-
});
3686+
};
36873687

36883688
do {
36893689
Pattern *pattern;

lib/Sema/IterativeTypeChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void IterativeTypeChecker::satisfy(TypeCheckRequest request) {
8484

8585
// Add this request to the stack of active requests.
8686
ActiveRequests.push_back(request);
87-
defer([&] { ActiveRequests.pop_back(); });
87+
defer { ActiveRequests.pop_back(); };
8888

8989
while (true) {
9090
// Process this requirement, enumerating dependencies if anything else needs

lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
356356
{
357357
bool iBTC = decl->isBeingTypeChecked();
358358
decl->setIsBeingTypeChecked();
359-
defer([&]{decl->setIsBeingTypeChecked(iBTC); });
359+
defer {decl->setIsBeingTypeChecked(iBTC); };
360360

361361
// Validate the type.
362362
if (validateType(inherited, DC, options, resolver)) {
@@ -1219,9 +1219,9 @@ static void validatePatternBindingDecl(TypeChecker &tc,
12191219

12201220
// On any path out of this function, make sure to mark the binding as done
12211221
// being type checked.
1222-
defer([&]{
1222+
defer {
12231223
binding->setIsBeingTypeChecked(false);
1224-
});
1224+
};
12251225

12261226
// Resolve the pattern.
12271227
auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
@@ -6239,7 +6239,7 @@ static Type checkExtensionGenericParams(
62396239
};
62406240

62416241
ext->setIsBeingTypeChecked(true);
6242-
defer([ext] { ext->setIsBeingTypeChecked(false); });
6242+
defer { ext->setIsBeingTypeChecked(false); };
62436243

62446244
// Validate the generic type signature.
62456245
bool invalid = false;

lib/Sema/TypeCheckExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ namespace {
890890
}
891891
// Recursively check the transitive captures.
892892
capturePath.push_back(func);
893-
defer([&]{ capturePath.pop_back(); });
893+
defer { capturePath.pop_back(); };
894894
for (auto capture : func->getCaptureInfo().getCaptures())
895895
if (!validateForwardCapture(capture.getDecl()))
896896
return false;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,9 +2922,9 @@ void ConformanceChecker::resolveTypeWitnesses() {
29222922
// Track when we are checking type witnesses.
29232923
ProtocolConformanceState initialState = Conformance->getState();
29242924
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
2925-
defer([&] {
2925+
defer {
29262926
Conformance->setState(initialState);
2927-
});
2927+
};
29282928

29292929
for (auto member : Proto->getMembers()) {
29302930
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
@@ -3251,11 +3251,11 @@ void ConformanceChecker::resolveTypeWitnesses() {
32513251
valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
32523252
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
32533253
++numValueWitnessesInProtocolExtensions;
3254-
defer([&]{
3254+
defer {
32553255
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
32563256
--numValueWitnessesInProtocolExtensions;
32573257
valueWitnesses.pop_back();
3258-
});
3258+
};
32593259

32603260
// Introduce each of the type witnesses into the hash table.
32613261
bool failed = false;
@@ -3635,7 +3635,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
36353635
// Note that we're resolving this witness.
36363636
assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
36373637
ResolvingWitnesses.insert(requirement);
3638-
defer([&]{ ResolvingWitnesses.erase(requirement); });
3638+
defer { ResolvingWitnesses.erase(requirement); };
36393639

36403640
// Make sure we've validated the requirement.
36413641
if (!requirement->hasType())
@@ -3934,7 +3934,7 @@ checkConformsToProtocol(TypeChecker &TC,
39343934

39353935
// Note that we are checking this conformance now.
39363936
conformance->setState(ProtocolConformanceState::Checking);
3937-
defer([&] { conformance->setState(ProtocolConformanceState::Complete); });
3937+
defer { conformance->setState(ProtocolConformanceState::Complete); };
39383938

39393939
// If the protocol requires a class, non-classes are a non-starter.
39403940
if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {

0 commit comments

Comments
 (0)