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
19 changes: 13 additions & 6 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4565,10 +4565,9 @@ class AbstractStorageDecl : public ValueDecl {
bool isSettable(const DeclContext *UseDC,
const DeclRefExpr *base = nullptr) const;

/// Are there any accessors for this declaration, including implicit ones?
bool hasAnyAccessors() const {
return !getAllAccessors().empty();
}
/// Does this storage declaration have explicitly-defined accessors
/// written in the source?
bool hasParsedAccessors() const;

/// Return the ownership of values opaquely read from this storage.
OpaqueReadOwnership getOpaqueReadOwnership() const;
Expand Down Expand Up @@ -4628,13 +4627,21 @@ class AbstractStorageDecl : public ValueDecl {
/// accessor was not explicitly defined by the user.
AccessorDecl *getParsedAccessor(AccessorKind kind) const;

/// Visit all the opaque accessors that this storage is expected to have.
/// Visit all parsed accessors.
void visitParsedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

/// Visit all opaque accessor kinds.
void visitExpectedOpaqueAccessors(
llvm::function_ref<void (AccessorKind)>) const;

/// Visit all the opaque accessors of this storage declaration.
/// Visit all opaque accessors.
void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

/// Visit all eagerly emitted accessors.
///
/// This is the union of the parsed and opaque sets.
void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Eagerly" emitted accessors, maybe?


void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
SourceLoc rbraceLoc);

Expand Down
7 changes: 7 additions & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/Ownership.h"
#include "swift/AST/ParameterList.h"
Expand Down Expand Up @@ -2323,6 +2324,12 @@ CanType ASTMangler::getDeclTypeForMangling(
parentGenericSig = nullptr;

auto &C = decl->getASTContext();
if (!decl->hasInterfaceType() && !decl->getDeclContext()->isLocalContext()) {
if (auto *resolver = C.getLazyResolver()) {
resolver->resolveDeclSignature(const_cast<ValueDecl *>(decl));
}
}

if (!decl->hasInterfaceType() || decl->getInterfaceType()->is<ErrorType>()) {
if (isa<AbstractFunctionDecl>(decl))
return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)},
Expand Down
6 changes: 3 additions & 3 deletions lib/AST/ASTScopeCreation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,8 @@ ASTScopeImpl *ScopeCreator::createScopeFor(ASTNode n, ASTScopeImpl *parent) {

void ScopeCreator::addChildrenForAllExplicitAccessors(AbstractStorageDecl *asd,
ASTScopeImpl *parent) {
for (auto accessor : asd->getAllAccessors()) {
if (!accessor->isImplicit() && accessor->getStartLoc().isValid()) {
asd->visitParsedAccessors([&](AccessorDecl *accessor) {
if (accessor->getStartLoc().isValid()) {
// Accessors are always nested within their abstract storage
// declaration. The nesting may not be immediate, because subscripts may
// have intervening scopes for generics.
Expand All @@ -526,7 +526,7 @@ void ScopeCreator::addChildrenForAllExplicitAccessors(AbstractStorageDecl *asd,
ASTVisitorForScopeCreation().visitAbstractFunctionDecl(accessor, parent,
*this);
}
}
});
}

#pragma mark creation helpers
Expand Down
48 changes: 34 additions & 14 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,13 @@ AccessorDecl *AbstractStorageDecl::getOpaqueAccessor(AccessorKind kind) const {
return getSynthesizedAccessor(kind);
}

bool AbstractStorageDecl::hasParsedAccessors() const {
for (auto *accessor : getAllAccessors())
if (!accessor->isImplicit())
return true;
return false;
}

AccessorDecl *AbstractStorageDecl::getParsedAccessor(AccessorKind kind) const {
auto *accessor = getAccessor(kind);
if (accessor && !accessor->isImplicit())
Expand All @@ -2018,6 +2025,22 @@ AccessorDecl *AbstractStorageDecl::getParsedAccessor(AccessorKind kind) const {
return nullptr;
}

void AbstractStorageDecl::visitParsedAccessors(
llvm::function_ref<void (AccessorDecl*)> visit) const {
for (auto *accessor : getAllAccessors())
if (!accessor->isImplicit())
visit(accessor);
}

void AbstractStorageDecl::visitEmittedAccessors(
llvm::function_ref<void (AccessorDecl*)> visit) const {
visitParsedAccessors(visit);
visitOpaqueAccessors([&](AccessorDecl *accessor) {
if (accessor->isImplicit())
visit(accessor);
});
}

void AbstractStorageDecl::visitExpectedOpaqueAccessors(
llvm::function_ref<void (AccessorKind)> visit) const {
if (!requiresOpaqueAccessors())
Expand Down Expand Up @@ -6440,13 +6463,6 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {

auto &ctx = dc->getASTContext();

// FIXME: Remove this once getInterfaceType(), isDesignatedInit() and
// anything else that is used below has been request-ified.
if (!decl->hasInterfaceType()) {
ctx.getLazyResolver()->resolveDeclSignature(
const_cast<AbstractFunctionDecl *>(decl));
}

// Initializers are not normally inherited, but required initializers can
// be overridden for invocation from dynamic types, and convenience initializers
// are conditionally inherited when all designated initializers are available,
Expand All @@ -6471,13 +6487,6 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
if (!base || base->hasClangNode() || base->isObjCDynamic())
return true;

// FIXME: Remove this once getInterfaceType(), isDesignatedInit() and
// anything else that is used below has been request-ified.
if (!base->hasInterfaceType()) {
ctx.getLazyResolver()->resolveDeclSignature(
const_cast<AbstractFunctionDecl *>(base));
}

// As above, convenience initializers are not formally overridable in Swift
// vtables, although same-named initializers are modeled as overriding for
// various QoI and objc interop reasons. Even if we "override" a non-required
Expand All @@ -6494,6 +6503,17 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
if (decl->isEffectiveLinkageMoreVisibleThan(base))
return true;

// FIXME: Remove this once getInterfaceType() has been request-ified.
if (!decl->hasInterfaceType()) {
ctx.getLazyResolver()->resolveDeclSignature(
const_cast<AbstractFunctionDecl *>(decl));
}

if (!base->hasInterfaceType()) {
ctx.getLazyResolver()->resolveDeclSignature(
const_cast<AbstractFunctionDecl *>(base));
}

// If the method overrides something, we only need a new entry if the
// override has a more general AST type. However an abstraction
// change is OK; we don't want to add a whole new vtable entry just
Expand Down
5 changes: 3 additions & 2 deletions lib/IDE/Refactoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1618,8 +1618,9 @@ class FindAllSubDecls : public SourceEntityWalker {
return false;

if (auto ASD = dyn_cast<AbstractStorageDecl>(D)) {
auto accessors = ASD->getAllAccessors();
Found.insert(accessors.begin(), accessors.end());
ASD->visitParsedAccessors([&](AccessorDecl *accessor) {
Found.insert(accessor);
});
}
return true;
}
Expand Down
10 changes: 4 additions & 6 deletions lib/Index/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1103,15 +1103,13 @@ bool IndexSwiftASTWalker::report(ValueDecl *D) {
// Even if we don't record a local property we still need to walk its
// accessor bodies.
if (auto StoreD = dyn_cast<AbstractStorageDecl>(D)) {
for (auto accessor : StoreD->getAllAccessors()) {
if (accessor->isImplicit())
continue;
StoreD->visitParsedAccessors([&](AccessorDecl *accessor) {
if (Cancelled)
return;
ManuallyVisitedAccessorStack.push_back(accessor);
SourceEntityWalker::walk(cast<Decl>(accessor));
ManuallyVisitedAccessorStack.pop_back();
if (Cancelled)
return false;
}
});
}
}

Expand Down
6 changes: 3 additions & 3 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1328,15 +1328,15 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
if (vd->hasStorage())
addGlobalVariable(vd);

for (auto *accessor : vd->getAllAccessors())
vd->visitEmittedAccessors([&](AccessorDecl *accessor) {
emitFunction(accessor);
});

tryEmitPropertyDescriptor(vd);
}

void SILGenModule::visitSubscriptDecl(SubscriptDecl *sd) {
for (auto *accessor : sd->getAllAccessors())
emitFunction(accessor);
llvm_unreachable("top-level subscript?");
}

bool
Expand Down
3 changes: 2 additions & 1 deletion lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,8 +1194,9 @@ void SILGenFunction::visitVarDecl(VarDecl *D) {
// We handle emitting the variable storage when we see the pattern binding.

// Emit the variable's accessors.
for (auto *accessor : D->getAllAccessors())
D->visitEmittedAccessors([&](AccessorDecl *accessor) {
SGM.emitFunction(accessor);
});
}

/// Emit literals for the major, minor, and subminor components of the version
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3360,7 +3360,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
// storage.
// Properties that are not public don't need property descriptors
// either.
(!baseDecl->hasAnyAccessors() ||
(!baseDecl->requiresOpaqueAccessors() ||
(!getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))
.isForeign &&
getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))
Expand Down
12 changes: 6 additions & 6 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,9 +1050,9 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
}

void visitAccessors(AbstractStorageDecl *asd) {
for (auto *accessor : asd->getAllAccessors())
if (!accessor->hasForcedStaticDispatch())
visitFuncDecl(accessor);
asd->visitEmittedAccessors([&](AccessorDecl *accessor) {
visitFuncDecl(accessor);
});
}
};

Expand Down Expand Up @@ -1182,9 +1182,9 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
}

void visitAccessors(AbstractStorageDecl *asd) {
for (auto *accessor : asd->getAllAccessors())
if (!accessor->hasForcedStaticDispatch())
visitFuncDecl(accessor);
asd->visitEmittedAccessors([&](AccessorDecl *accessor) {
visitFuncDecl(accessor);
});
}
};

Expand Down
1 change: 0 additions & 1 deletion lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4039,7 +4039,6 @@ namespace {
method = func;
} else if (auto var = dyn_cast<VarDecl>(foundDecl)) {
// Properties.
addExpectedOpaqueAccessorsToStorage(var);

// If this isn't a property on a type, complain.
if (!var->getDeclContext()->isTypeContext()) {
Expand Down
8 changes: 0 additions & 8 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1293,13 +1293,6 @@ SynthesizeAccessorRequest::evaluate(Evaluator &evaluator,
}
}

void swift::addExpectedOpaqueAccessorsToStorage(AbstractStorageDecl *storage) {
storage->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
// Force synthesis if necessary.
(void) storage->getSynthesizedAccessor(kind);
});
}

/// Synthesize the body of a setter which just delegates to a mutable
/// addressor.
static std::pair<BraceStmt *, bool>
Expand Down Expand Up @@ -1717,7 +1710,6 @@ static VarDecl *synthesizePropertyWrapperStorageWrapperProperty(
property->setImplInfo(StorageImplInfo::getMutableComputed());
else
property->setImplInfo(StorageImplInfo::getImmutableComputed());
addExpectedOpaqueAccessorsToStorage(property);

var->getAttrs().add(
new (ctx) ProjectedValuePropertyAttr(name, SourceLoc(), SourceRange(),
Expand Down
3 changes: 0 additions & 3 deletions lib/Sema/CodeSynthesis.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ class ObjCReason;
// Implemented in TypeCheckerOverride.cpp
bool checkOverrides(ValueDecl *decl);

// These are implemented in CodeSynthesis.cpp.
void addExpectedOpaqueAccessorsToStorage(AbstractStorageDecl *storage);

/// Describes the kind of implicit constructor that will be
/// generated.
enum class ImplicitConstructorKind {
Expand Down
57 changes: 30 additions & 27 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2140,23 +2140,24 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
}

// Find the accessor in the replaced storage decl.
for (auto *origAccessor : origStorage->getAllAccessors()) {
TC.validateDecl(origAccessor);
if (origAccessor->getAccessorKind() != replacement->getAccessorKind())
continue;
auto *origAccessor = origStorage->getOpaqueAccessor(
replacement->getAccessorKind());
if (!origAccessor)
return nullptr;

if (origAccessor->isImplicit() &&
!(origStorage->getReadImpl() == ReadImplKind::Stored &&
origStorage->getWriteImpl() == WriteImplKind::Stored)) {
TC.diagnose(attr->getLocation(),
diag::dynamic_replacement_accessor_not_explicit,
(unsigned)origAccessor->getAccessorKind(), replacedVarName);
attr->setInvalid();
return nullptr;
}
return origAccessor;
TC.validateDecl(origAccessor);

if (origAccessor->isImplicit() &&
!(origStorage->getReadImpl() == ReadImplKind::Stored &&
origStorage->getWriteImpl() == WriteImplKind::Stored)) {
TC.diagnose(attr->getLocation(),
diag::dynamic_replacement_accessor_not_explicit,
(unsigned)origAccessor->getAccessorKind(), replacedVarName);
attr->setInvalid();
return nullptr;
}
return nullptr;

return origAccessor;
}

static AbstractFunctionDecl *
Expand Down Expand Up @@ -2298,19 +2299,19 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {

// Collect the accessor replacement mapping if this is an abstract storage.
if (auto *var = dyn_cast<AbstractStorageDecl>(D)) {
for (auto *accessor : var->getAllAccessors()) {
var->visitParsedAccessors([&](AccessorDecl *accessor) {
if (attr->isInvalid())
return;

validateDecl(accessor);
if (accessor->isImplicit())
continue;
auto *orig = findReplacedAccessor(attr->getReplacedFunctionName(),
accessor, attr, *this);
if (attr->isInvalid())
return;
if (!orig)
continue;
return;

origs.push_back(orig);
replacements.push_back(accessor);
}
});
} else {
// Otherwise, find the matching function.
auto *fun = cast<AbstractFunctionDecl>(D);
Expand Down Expand Up @@ -2823,12 +2824,14 @@ void TypeChecker::addImplicitDynamicAttribute(Decl *D) {
return;
}

// Don't add dynamic if accessor is inlinable or tranparent.
// Don't add dynamic if accessor is inlinable or transparent.
if (auto *asd = dyn_cast<AbstractStorageDecl>(D)) {
for (auto *accessor : asd->getAllAccessors()) {
if (!accessor->isImplicit() && shouldBlockImplicitDynamic(accessor))
return;
}
bool blocked = false;
asd->visitParsedAccessors([&](AccessorDecl *accessor) {
blocked |= shouldBlockImplicitDynamic(accessor);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the typo in the comment while you're here.

if (blocked)
return;
}

if (auto *VD = dyn_cast<VarDecl>(D)) {
Expand Down
Loading