mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Make c++ defer looks like a swift one
This commit is contained in:
@@ -18,11 +18,12 @@
|
|||||||
#ifndef __SWIFT_DEFER_H
|
#ifndef __SWIFT_DEFER_H
|
||||||
#define __SWIFT_DEFER_H
|
#define __SWIFT_DEFER_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
class DoAtScopeExit {
|
class DoAtScopeExit {
|
||||||
F &Fn;
|
F &Fn;
|
||||||
DoAtScopeExit(DoAtScopeExit&) = delete;
|
|
||||||
void operator=(DoAtScopeExit&) = delete;
|
void operator=(DoAtScopeExit&) = delete;
|
||||||
public:
|
public:
|
||||||
DoAtScopeExit(F &Fn) : Fn(Fn){}
|
DoAtScopeExit(F &Fn) : Fn(Fn){}
|
||||||
@@ -30,8 +31,17 @@ namespace swift {
|
|||||||
Fn();
|
Fn();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
struct DeferTask {};
|
||||||
|
template<typename F>
|
||||||
|
DoAtScopeExit<typename std::decay<F>::type> operator+(DeferTask, F&& fn) {
|
||||||
|
return DoAtScopeExit<typename std::decay<F>::type>(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DEFER_CONCAT_IMPL(x, y) x##y
|
#define DEFER_CONCAT_IMPL(x, y) x##y
|
||||||
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
|
#define DEFER_MACRO_CONCAT(x, y) DEFER_CONCAT_IMPL(x, y)
|
||||||
|
|
||||||
@@ -39,16 +49,13 @@ namespace swift {
|
|||||||
/// This macro is used to register a function / lambda to be run on exit from a
|
/// This macro is used to register a function / lambda to be run on exit from a
|
||||||
/// scope. Its typical use looks like:
|
/// scope. Its typical use looks like:
|
||||||
///
|
///
|
||||||
/// defer([&]{
|
/// defer {
|
||||||
/// stuff
|
/// stuff
|
||||||
/// })
|
/// };
|
||||||
///
|
///
|
||||||
#define defer(x) \
|
#define defer \
|
||||||
auto DEFER_MACRO_CONCAT(defer_func, __LINE__) = (x); \
|
auto DEFER_MACRO_CONCAT(defer_func, __COUNTER__) = \
|
||||||
swift::DoAtScopeExit<decltype(DEFER_MACRO_CONCAT(defer_func, __LINE__))> \
|
::swift::detail::DeferTask() + [&]()
|
||||||
DEFER_MACRO_CONCAT(defer_local, __LINE__)\
|
|
||||||
(DEFER_MACRO_CONCAT(defer_func, __LINE__));
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3643,7 +3643,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
|
|
||||||
// No matter what error path we take, make sure the
|
// No matter what error path we take, make sure the
|
||||||
// PatternBindingDecl/TopLevel code block are added.
|
// PatternBindingDecl/TopLevel code block are added.
|
||||||
defer([&]{
|
defer {
|
||||||
// If we didn't parse any patterns, don't create the pattern binding decl.
|
// If we didn't parse any patterns, don't create the pattern binding decl.
|
||||||
if (PBDEntries.empty())
|
if (PBDEntries.empty())
|
||||||
return;
|
return;
|
||||||
@@ -3683,7 +3683,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// specific spot to get it in before any accessors, which SILGen seems to
|
// specific spot to get it in before any accessors, which SILGen seems to
|
||||||
// want.
|
// want.
|
||||||
Decls.insert(Decls.begin()+NumDeclsInResult, PBD);
|
Decls.insert(Decls.begin()+NumDeclsInResult, PBD);
|
||||||
});
|
};
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Pattern *pattern;
|
Pattern *pattern;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void IterativeTypeChecker::satisfy(TypeCheckRequest request) {
|
|||||||
|
|
||||||
// Add this request to the stack of active requests.
|
// Add this request to the stack of active requests.
|
||||||
ActiveRequests.push_back(request);
|
ActiveRequests.push_back(request);
|
||||||
defer([&] { ActiveRequests.pop_back(); });
|
defer { ActiveRequests.pop_back(); };
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Process this requirement, enumerating dependencies if anything else needs
|
// Process this requirement, enumerating dependencies if anything else needs
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
|
|||||||
{
|
{
|
||||||
bool iBTC = decl->isBeingTypeChecked();
|
bool iBTC = decl->isBeingTypeChecked();
|
||||||
decl->setIsBeingTypeChecked();
|
decl->setIsBeingTypeChecked();
|
||||||
defer([&]{decl->setIsBeingTypeChecked(iBTC); });
|
defer {decl->setIsBeingTypeChecked(iBTC); };
|
||||||
|
|
||||||
// Validate the type.
|
// Validate the type.
|
||||||
if (validateType(inherited, DC, options, resolver)) {
|
if (validateType(inherited, DC, options, resolver)) {
|
||||||
@@ -1219,9 +1219,9 @@ static void validatePatternBindingDecl(TypeChecker &tc,
|
|||||||
|
|
||||||
// On any path out of this function, make sure to mark the binding as done
|
// On any path out of this function, make sure to mark the binding as done
|
||||||
// being type checked.
|
// being type checked.
|
||||||
defer([&]{
|
defer {
|
||||||
binding->setIsBeingTypeChecked(false);
|
binding->setIsBeingTypeChecked(false);
|
||||||
});
|
};
|
||||||
|
|
||||||
// Resolve the pattern.
|
// Resolve the pattern.
|
||||||
auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
|
auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
|
||||||
@@ -6239,7 +6239,7 @@ static Type checkExtensionGenericParams(
|
|||||||
};
|
};
|
||||||
|
|
||||||
ext->setIsBeingTypeChecked(true);
|
ext->setIsBeingTypeChecked(true);
|
||||||
defer([ext] { ext->setIsBeingTypeChecked(false); });
|
defer { ext->setIsBeingTypeChecked(false); };
|
||||||
|
|
||||||
// Validate the generic type signature.
|
// Validate the generic type signature.
|
||||||
bool invalid = false;
|
bool invalid = false;
|
||||||
|
|||||||
@@ -890,7 +890,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
// Recursively check the transitive captures.
|
// Recursively check the transitive captures.
|
||||||
capturePath.push_back(func);
|
capturePath.push_back(func);
|
||||||
defer([&]{ capturePath.pop_back(); });
|
defer { capturePath.pop_back(); };
|
||||||
for (auto capture : func->getCaptureInfo().getCaptures())
|
for (auto capture : func->getCaptureInfo().getCaptures())
|
||||||
if (!validateForwardCapture(capture.getDecl()))
|
if (!validateForwardCapture(capture.getDecl()))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -2922,9 +2922,9 @@ void ConformanceChecker::resolveTypeWitnesses() {
|
|||||||
// Track when we are checking type witnesses.
|
// Track when we are checking type witnesses.
|
||||||
ProtocolConformanceState initialState = Conformance->getState();
|
ProtocolConformanceState initialState = Conformance->getState();
|
||||||
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
|
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
|
||||||
defer([&] {
|
defer {
|
||||||
Conformance->setState(initialState);
|
Conformance->setState(initialState);
|
||||||
});
|
};
|
||||||
|
|
||||||
for (auto member : Proto->getMembers()) {
|
for (auto member : Proto->getMembers()) {
|
||||||
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
|
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
|
||||||
@@ -3251,11 +3251,11 @@ void ConformanceChecker::resolveTypeWitnesses() {
|
|||||||
valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
|
valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
|
||||||
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
||||||
++numValueWitnessesInProtocolExtensions;
|
++numValueWitnessesInProtocolExtensions;
|
||||||
defer([&]{
|
defer {
|
||||||
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
if (witnessReq.Witness->getDeclContext()->isProtocolExtensionContext())
|
||||||
--numValueWitnessesInProtocolExtensions;
|
--numValueWitnessesInProtocolExtensions;
|
||||||
valueWitnesses.pop_back();
|
valueWitnesses.pop_back();
|
||||||
});
|
};
|
||||||
|
|
||||||
// Introduce each of the type witnesses into the hash table.
|
// Introduce each of the type witnesses into the hash table.
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
@@ -3635,7 +3635,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
|
|||||||
// Note that we're resolving this witness.
|
// Note that we're resolving this witness.
|
||||||
assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
|
assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
|
||||||
ResolvingWitnesses.insert(requirement);
|
ResolvingWitnesses.insert(requirement);
|
||||||
defer([&]{ ResolvingWitnesses.erase(requirement); });
|
defer { ResolvingWitnesses.erase(requirement); };
|
||||||
|
|
||||||
// Make sure we've validated the requirement.
|
// Make sure we've validated the requirement.
|
||||||
if (!requirement->hasType())
|
if (!requirement->hasType())
|
||||||
@@ -3934,7 +3934,7 @@ checkConformsToProtocol(TypeChecker &TC,
|
|||||||
|
|
||||||
// Note that we are checking this conformance now.
|
// Note that we are checking this conformance now.
|
||||||
conformance->setState(ProtocolConformanceState::Checking);
|
conformance->setState(ProtocolConformanceState::Checking);
|
||||||
defer([&] { conformance->setState(ProtocolConformanceState::Complete); });
|
defer { conformance->setState(ProtocolConformanceState::Complete); };
|
||||||
|
|
||||||
// If the protocol requires a class, non-classes are a non-starter.
|
// If the protocol requires a class, non-classes are a non-starter.
|
||||||
if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
|
if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user