From 3d160d956a69551deb5173f308d19527f7dd6c70 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 9 Oct 2020 18:16:18 -0400 Subject: [PATCH] Sema: Move SimpleDidSetRequest::evaluate() to TypeCheckStorage.cpp I think TypeCheckStorage.cpp is a better place for this than TypeCheckDecl.cpp, since all the other requests for storage and accessor declarations appear in the former. --- lib/Sema/TypeCheckDecl.cpp | 67 ---------------------------------- lib/Sema/TypeCheckStorage.cpp | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 3e21327297eba..66240cc334e70 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1273,73 +1273,6 @@ EnumRawValuesRequest::evaluate(Evaluator &eval, EnumDecl *ED, return std::make_tuple<>(); } -bool SimpleDidSetRequest::evaluate(Evaluator &evaluator, - AccessorDecl *decl) const { - - class OldValueFinder : public ASTWalker { - const ParamDecl *OldValueParam; - bool foundOldValueRef = false; - - public: - OldValueFinder(const ParamDecl *param) : OldValueParam(param) {} - - virtual std::pair walkToExprPre(Expr *E) override { - if (!E) - return {true, E}; - if (auto DRE = dyn_cast(E)) { - if (auto decl = DRE->getDecl()) { - if (decl == OldValueParam) { - foundOldValueRef = true; - return {false, nullptr}; - } - } - } - - return {true, E}; - } - - bool didFindOldValueRef() { return foundOldValueRef; } - }; - - // If this is not a didSet accessor, bail out. - if (decl->getAccessorKind() != AccessorKind::DidSet) { - return false; - } - - // Always assume non-simple 'didSet' in code completion mode. - if (decl->getASTContext().SourceMgr.hasCodeCompletionBuffer()) - return false; - - // didSet must have a single parameter. - if (decl->getParameters()->size() != 1) { - return false; - } - - auto param = decl->getParameters()->get(0); - // If this parameter is not implicit, then it means it has been explicitly - // provided by the user (i.e. 'didSet(oldValue)'). This means we cannot - // consider this a "simple" didSet because we have to fetch the oldValue - // regardless of whether it's referenced in the body or not. - if (!param->isImplicit()) { - return false; - } - - // If we find a reference to the implicit 'oldValue' parameter, then it is - // not a "simple" didSet because we need to fetch it. - auto walker = OldValueFinder(param); - decl->getTypecheckedBody()->walk(walker); - auto hasOldValueRef = walker.didFindOldValueRef(); - if (!hasOldValueRef) { - // If the body does not refer to implicit 'oldValue', it means we can - // consider this as a "simple" didSet. Let's also erase the implicit - // oldValue as it is never used. - auto &ctx = decl->getASTContext(); - decl->setParameters(ParameterList::createEmpty(ctx)); - return true; - } - return false; -} - const ConstructorDecl * swift::findNonImplicitRequiredInit(const ConstructorDecl *CD) { while (CD->isImplicit()) { diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index c9a4c5a2cf9f1..e507d3e3322a1 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -3186,3 +3186,71 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator, return info; } + +bool SimpleDidSetRequest::evaluate(Evaluator &evaluator, + AccessorDecl *decl) const { + + class OldValueFinder : public ASTWalker { + const ParamDecl *OldValueParam; + bool foundOldValueRef = false; + + public: + OldValueFinder(const ParamDecl *param) : OldValueParam(param) {} + + virtual std::pair walkToExprPre(Expr *E) override { + if (!E) + return {true, E}; + if (auto DRE = dyn_cast(E)) { + if (auto decl = DRE->getDecl()) { + if (decl == OldValueParam) { + foundOldValueRef = true; + return {false, nullptr}; + } + } + } + + return {true, E}; + } + + bool didFindOldValueRef() { return foundOldValueRef; } + }; + + // If this is not a didSet accessor, bail out. + if (decl->getAccessorKind() != AccessorKind::DidSet) { + return false; + } + + // Always assume non-simple 'didSet' in code completion mode. + if (decl->getASTContext().SourceMgr.hasCodeCompletionBuffer()) + return false; + + // didSet must have a single parameter. + if (decl->getParameters()->size() != 1) { + return false; + } + + auto param = decl->getParameters()->get(0); + // If this parameter is not implicit, then it means it has been explicitly + // provided by the user (i.e. 'didSet(oldValue)'). This means we cannot + // consider this a "simple" didSet because we have to fetch the oldValue + // regardless of whether it's referenced in the body or not. + if (!param->isImplicit()) { + return false; + } + + // If we find a reference to the implicit 'oldValue' parameter, then it is + // not a "simple" didSet because we need to fetch it. + auto walker = OldValueFinder(param); + decl->getTypecheckedBody()->walk(walker); + auto hasOldValueRef = walker.didFindOldValueRef(); + if (!hasOldValueRef) { + // If the body does not refer to implicit 'oldValue', it means we can + // consider this as a "simple" didSet. Let's also erase the implicit + // oldValue as it is never used. + auto &ctx = decl->getASTContext(); + decl->setParameters(ParameterList::createEmpty(ctx)); + return true; + } + return false; +} +