Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 0 additions & 67 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool, Expr *> walkToExprPre(Expr *E) override {
if (!E)
return {true, E};
if (auto DRE = dyn_cast<DeclRefExpr>(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()) {
Expand Down
68 changes: 68 additions & 0 deletions lib/Sema/TypeCheckStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool, Expr *> walkToExprPre(Expr *E) override {
if (!E)
return {true, E};
if (auto DRE = dyn_cast<DeclRefExpr>(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;
}