Skip to content

[Type checker] Move accessor creation out of validateDecl(). #19259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2018
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
2 changes: 2 additions & 0 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===//

#include "ConstraintSystem.h"
#include "CodeSynthesis.h"
#include "CSDiagnostics.h"
#include "MiscDiagnostics.h"
#include "TypeCheckProtocol.h"
Expand Down Expand Up @@ -4112,6 +4113,7 @@ namespace {
method = func;
} else if (auto var = dyn_cast<VarDecl>(foundDecl)) {
// Properties.
maybeAddAccessorsToStorage(tc, var);

// If this isn't a property on a type, complain.
if (!var->getDeclContext()->isTypeContext()) {
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,7 @@ static bool wouldBeCircularSynthesis(AbstractStorageDecl *storage,
void swift::triggerAccessorSynthesis(TypeChecker &TC,
AbstractStorageDecl *storage) {
auto VD = dyn_cast<VarDecl>(storage);
maybeAddAccessorsToStorage(TC, storage);

// Synthesize accessors for lazy, all checking already been performed.
bool lazy = false;
Expand Down
15 changes: 11 additions & 4 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) {
// No behavior, no problems.
if (!decl->hasBehavior())
return;

// Don't try to check the behavior if we already encountered an error.
if (decl->getType()->hasError())
return;
Expand Down Expand Up @@ -2262,9 +2262,6 @@ static void validateAbstractStorageDecl(TypeChecker &TC,
storage->setIsGetterMutating(computeIsGetterMutating(TC, storage));
storage->setIsSetterMutating(computeIsSetterMutating(TC, storage));

// Add any mandatory accessors now.
maybeAddAccessorsToStorage(TC, storage);

// Everything else about the accessors can wait until finalization.
// This will validate all the accessors.
TC.DeclsToFinalize.insert(storage);
Expand All @@ -2274,9 +2271,15 @@ static void finalizeAbstractStorageDecl(TypeChecker &TC,
AbstractStorageDecl *storage) {
TC.validateDecl(storage);

// Add any mandatory accessors now.
maybeAddAccessorsToStorage(TC, storage);

for (auto accessor : storage->getAllAccessors()) {
// Are there accessors we can safely ignore here, like maybe observers?
TC.validateDecl(accessor);

// Finalize the accessors as well.
TC.DeclsToFinalize.insert(accessor);
}
}

Expand Down Expand Up @@ -2373,6 +2376,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
void visitBoundVariable(VarDecl *VD) {
TC.validateDecl(VD);

// Set up accessors.
maybeAddAccessorsToStorage(TC, VD);

// Check the behavior.
checkVarBehavior(VD, TC);

Expand Down Expand Up @@ -4606,6 +4612,7 @@ void TypeChecker::requestMemberLayout(ValueDecl *member) {
// because if they never get validated at all then conformance checkers
// will complain about selector mismatches.
if (storage->isObjC()) {
maybeAddAccessorsToStorage(*this, storage);
for (auto accessor : storage->getAllAccessors()) {
requestMemberLayout(accessor);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/Sema/TypeCheckDeclOverride.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,13 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
if (!shouldDiagnose && baseDecl->isSettable(dc)){
auto matchASD = cast<AbstractStorageDecl>(baseDecl);
if (matchASD->isSetterAccessibleFrom(dc)) {
// Match sure we've created the setter.
if (!matchASD->getSetter()) {
maybeAddAccessorsToStorage(
*static_cast<TypeChecker *>(ctx.getLazyResolver()),
matchASD);
}

auto matchSetterAccessScope = matchASD->getSetter()
->getFormalAccessScope(dc);
auto requiredSetterAccessScope =
Expand Down Expand Up @@ -1753,8 +1760,14 @@ OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {

// Check the various overridden storage declarations.
SmallVector<OverrideMatch, 2> matches;
ASTContext &ctx = decl->getASTContext();
for (auto overridden : overridingASD->getOverriddenDecls()) {
auto baseASD = cast<AbstractStorageDecl>(overridden);
if (auto lazyResolver = ctx.getLazyResolver()) {
maybeAddAccessorsToStorage(*static_cast<TypeChecker *>(lazyResolver),
baseASD);
}

auto kind = accessor->getAccessorKind();

// If the base doesn't consider this an opaque accessor,
Expand Down
13 changes: 13 additions & 0 deletions test/CircularReferences/objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,16 @@
class A {
@objc func foo() { }
}


@objc class B {
@objc dynamic subscript(i: Int) -> B {
return self
}
}

class C: B {
override subscript(i: Int) -> B {
return super[i]
}
}