Skip to content

Commit 12fa06a

Browse files
authored
Merge pull request swiftlang#26316 from slavapestov/finish-storage-impl-info
Sema: Move finishStorageImplInfo() to StorageImplInfoRequest evaluation
2 parents 4c45b51 + 2970c3c commit 12fa06a

File tree

10 files changed

+175
-200
lines changed

10 files changed

+175
-200
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,6 @@ ERROR(observing_accessor_conflicts_with_accessor,none,
304304
(unsigned, StringRef))
305305
ERROR(observing_accessor_in_subscript,none,
306306
"%select{'willSet'|'didSet'}0 is not allowed in subscripts", (unsigned))
307-
ERROR(getset_init,none,
308-
"variable with getter/setter cannot have an initial value", ())
309307
ERROR(getset_cannot_be_implied,none,
310308
"variable with implied type cannot have implied getter/setter", ())
311309

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,9 @@ WARNING(enum_frozen_nonpublic,none,
13771377
"%0 has no effect on non-public enums", (DeclAttribute))
13781378

13791379
// Variables (var and let).
1380+
ERROR(getset_init,none,
1381+
"variable with getter/setter cannot have an initial value", ())
1382+
13801383
ERROR(unimplemented_static_var,none,
13811384
"%select{ERROR|static|class}1 stored properties not supported"
13821385
"%select{ in this context| in generic types| in classes| in protocol extensions}0"

lib/IDE/SourceEntityWalker.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -182,25 +182,6 @@ bool SemaAnnotator::walkToDeclPost(Decl *D) {
182182
if (shouldIgnore(D, ShouldVisitChildren))
183183
return true;
184184

185-
// FIXME: rdar://17671977 the initializer for a lazy property has already
186-
// been moved into its implicit getter.
187-
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
188-
if (auto *VD = PBD->getSingleVar()) {
189-
if (VD->getAttrs().hasAttribute<LazyAttr>()) {
190-
if (auto *Get = VD->getGetter()) {
191-
assert((Get->isImplicit() || Get->isInvalid())
192-
&& "lazy var getter must be either implicitly computed or invalid");
193-
194-
// Note that an implicit getter may not have the body synthesized
195-
// in case the owning PatternBindingDecl is invalid.
196-
if (auto *Body = Get->getBody()) {
197-
Body->walk(*this);
198-
}
199-
}
200-
}
201-
}
202-
}
203-
204185
if (isa<ExtensionDecl>(D)) {
205186
assert(ExtDecls.back() == D);
206187
ExtDecls.pop_back();

lib/Parse/ParseDecl.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4896,15 +4896,6 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
48964896
Invalid = true;
48974897
}
48984898

4899-
// Lazy var should not have explicit getter/setter.
4900-
// For error-recovery, we mark them as invalid.
4901-
if (Attributes.hasAttribute<LazyAttr>()){
4902-
if (accessors.Get)
4903-
accessors.Get->setInvalid();
4904-
if (accessors.Set)
4905-
accessors.Set->setInvalid();
4906-
}
4907-
49084899
accessors.record(*this, PrimaryVar, Invalid, Decls);
49094900

49104901
return makeParserResult(PrimaryVar);
@@ -5256,11 +5247,6 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
52565247
// global, record it.
52575248
PBDEntries.back().setInitContext(initContext);
52585249

5259-
// If the attributes include @lazy, flag that on each initializer.
5260-
if (Attributes.hasAttribute<LazyAttr>()) {
5261-
PBDEntries.back().setInitializerSubsumed();
5262-
}
5263-
52645250
if (init.hasCodeCompletion()) {
52655251
Status |= init;
52665252
// If we are doing second pass of code completion, we don't want to
@@ -5282,12 +5268,6 @@ Parser::parseDeclVar(ParseDeclOptions Flags,
52825268
PatternInit != nullptr, Attributes, Decls);
52835269
if (boundVar.hasCodeCompletion())
52845270
return makeResult(makeParserCodeCompletionStatus());
5285-
if (PatternInit && boundVar.isNonNull() &&
5286-
!boundVar.get()->hasStorage()) {
5287-
diagnose(pattern->getLoc(), diag::getset_init)
5288-
.highlight(PatternInit->getSourceRange());
5289-
PatternInit = nullptr;
5290-
}
52915271
}
52925272

52935273
// Add all parsed vardecls to this scope.

lib/Sema/CodeSynthesis.cpp

Lines changed: 127 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,7 @@ synthesizeLazyGetterBody(AccessorDecl *Get, VarDecl *VD, VarDecl *Storage,
16251625
auto *InitValue = VD->getParentInitializer();
16261626
auto PBD = VD->getParentPatternBinding();
16271627
unsigned entryIndex = PBD->getPatternEntryIndexForVarDecl(VD);
1628-
assert(PBD->isInitializerSubsumed(entryIndex));
1628+
PBD->setInitializerSubsumed(entryIndex);
16291629

16301630
if (!PBD->isInitializerChecked(entryIndex))
16311631
TC.typeCheckPatternBinding(PBD, entryIndex);
@@ -2025,31 +2025,19 @@ void swift::triggerAccessorSynthesis(TypeChecker &TC,
20252025
});
20262026
}
20272027

2028-
static StorageImplInfo getProtocolStorageImpl(AbstractStorageDecl *storage) {
2029-
auto protocol = cast<ProtocolDecl>(storage->getDeclContext());
2030-
if (protocol->isObjC()) {
2031-
return StorageImplInfo::getComputed(storage->supportsMutation());
2032-
} else {
2033-
return StorageImplInfo::getOpaque(storage->supportsMutation(),
2034-
storage->getOpaqueReadOwnership());
2035-
}
2036-
}
2037-
20382028
/// Given a storage declaration in a protocol, set it up with the right
20392029
/// StorageImpl and add the right set of opaque accessors.
2040-
static void finishProtocolStorageImplInfo(AbstractStorageDecl *storage) {
2030+
static void finishProtocolStorageImplInfo(AbstractStorageDecl *storage,
2031+
StorageImplInfo &info) {
20412032
if (auto *var = dyn_cast<VarDecl>(storage)) {
2042-
if (var->hasStorage()) {
2043-
auto &ctx = var->getASTContext();
2033+
if (info.hasStorage()) {
20442034
// Protocols cannot have stored properties.
20452035
if (var->isLet()) {
2046-
ctx.Diags.diagnose(var->getLoc(),
2047-
diag::protocol_property_must_be_computed_var)
2036+
var->diagnose(diag::protocol_property_must_be_computed_var)
20482037
.fixItReplace(var->getParentPatternBinding()->getLoc(), "var")
20492038
.fixItInsertAfter(var->getTypeLoc().getLoc(), " { get }");
20502039
} else {
2051-
auto diag = ctx.Diags.diagnose(var->getLoc(),
2052-
diag::protocol_property_must_be_computed);
2040+
auto diag = var->diagnose(diag::protocol_property_must_be_computed);
20532041
auto braces = var->getBracesRange();
20542042

20552043
if (braces.isValid())
@@ -2060,15 +2048,59 @@ static void finishProtocolStorageImplInfo(AbstractStorageDecl *storage) {
20602048
}
20612049
}
20622050

2063-
storage->setImplInfo(getProtocolStorageImpl(storage));
2051+
auto protocol = cast<ProtocolDecl>(storage->getDeclContext());
2052+
if (protocol->isObjC()) {
2053+
info = StorageImplInfo::getComputed(info.supportsMutation());
2054+
} else {
2055+
info = StorageImplInfo::getOpaque(info.supportsMutation(),
2056+
storage->getOpaqueReadOwnership());
2057+
}
20642058
}
20652059

2066-
static void finishLazyVariableImplInfo(VarDecl *var) {
2067-
// If there are already accessors, something is invalid; bail out.
2068-
if (!var->getImplInfo().isSimpleStored())
2069-
return;
2060+
/// This emits a diagnostic with a fixit to remove the attribute.
2061+
template<typename ...ArgTypes>
2062+
void diagnoseAndRemoveAttr(Decl *D, DeclAttribute *attr,
2063+
ArgTypes &&...Args) {
2064+
auto &ctx = D->getASTContext();
2065+
ctx.Diags.diagnose(attr->getLocation(), std::forward<ArgTypes>(Args)...)
2066+
.fixItRemove(attr->getRangeWithAt());
2067+
}
2068+
2069+
static void finishLazyVariableImplInfo(VarDecl *var,
2070+
StorageImplInfo &info) {
2071+
auto *attr = var->getAttrs().getAttribute<LazyAttr>();
2072+
2073+
// It cannot currently be used on let's since we don't have a mutability model
2074+
// that supports it.
2075+
if (var->isLet())
2076+
diagnoseAndRemoveAttr(var, attr, diag::lazy_not_on_let);
2077+
2078+
// lazy must have an initializer.
2079+
if (!var->getParentInitializer())
2080+
diagnoseAndRemoveAttr(var, attr, diag::lazy_requires_initializer);
2081+
2082+
bool invalid = false;
20702083

2071-
var->setImplInfo(StorageImplInfo::getMutableComputed());
2084+
if (isa<ProtocolDecl>(var->getDeclContext())) {
2085+
diagnoseAndRemoveAttr(var, attr, diag::lazy_not_in_protocol);
2086+
invalid = true;
2087+
}
2088+
2089+
// Lazy properties must be written as stored properties in the source.
2090+
if (!info.isSimpleStored()) {
2091+
diagnoseAndRemoveAttr(var, attr,
2092+
info.hasStorage()
2093+
? diag::lazy_not_observable
2094+
: diag::lazy_not_on_computed);
2095+
invalid = true;
2096+
}
2097+
2098+
// The pattern binding must only bind a single variable.
2099+
if (!var->getParentPatternBinding()->getSingleVar())
2100+
diagnoseAndRemoveAttr(var, attr, diag::lazy_requires_single_var);
2101+
2102+
if (!invalid)
2103+
info = StorageImplInfo::getMutableComputed();
20722104
}
20732105

20742106
/// Determine whether all of the wrapped-value setters for the property
@@ -2090,8 +2122,21 @@ static bool allPropertyWrapperValueSettersAreAccessible(VarDecl *var) {
20902122
return true;
20912123
}
20922124

2093-
static void finishPropertyWrapperImplInfo(VarDecl *var) {
2125+
static void finishPropertyWrapperImplInfo(VarDecl *var,
2126+
StorageImplInfo &info) {
20942127
auto parentSF = var->getDeclContext()->getParentSourceFile();
2128+
if (!parentSF)
2129+
return;
2130+
2131+
// Properties with wrappers must not declare a getter or setter.
2132+
if (!info.hasStorage() && parentSF->Kind != SourceFileKind::Interface) {
2133+
auto &ctx = parentSF->getASTContext();
2134+
for (auto attr : var->getAttrs().getAttributes<CustomAttr>())
2135+
ctx.Diags.diagnose(attr->getLocation(), diag::property_wrapper_computed);
2136+
2137+
return;
2138+
}
2139+
20952140
bool wrapperSetterIsUsable =
20962141
var->getSetter() ||
20972142
(parentSF &&
@@ -2100,36 +2145,68 @@ static void finishPropertyWrapperImplInfo(VarDecl *var) {
21002145
allPropertyWrapperValueSettersAreAccessible(var));
21012146

21022147
if (wrapperSetterIsUsable)
2103-
var->setImplInfo(StorageImplInfo::getMutableComputed());
2148+
info = StorageImplInfo::getMutableComputed();
21042149
else
2105-
var->setImplInfo(StorageImplInfo::getImmutableComputed());
2150+
info = StorageImplInfo::getImmutableComputed();
21062151
}
21072152

2108-
static void finishNSManagedImplInfo(VarDecl *VD) {
2109-
// If it's not still stored, just bail out.
2110-
if (!VD->getImplInfo().isSimpleStored())
2111-
return;
2153+
static void finishNSManagedImplInfo(VarDecl *var,
2154+
StorageImplInfo &info) {
2155+
auto *attr = var->getAttrs().getAttribute<NSManagedAttr>();
21122156

2113-
VD->setImplInfo(StorageImplInfo::getMutableComputed());
2114-
}
2157+
if (var->isLet())
2158+
diagnoseAndRemoveAttr(var, attr, diag::attr_NSManaged_let_property);
21152159

2116-
static void finishStorageImplInfo(AbstractStorageDecl *storage) {
2117-
if (isa<ProtocolDecl>(storage->getDeclContext())) {
2118-
finishProtocolStorageImplInfo(storage);
2119-
return;
2160+
auto diagnoseNotStored = [&](unsigned kind) {
2161+
diagnoseAndRemoveAttr(var, attr, diag::attr_NSManaged_not_stored, kind);
2162+
};
2163+
2164+
// @NSManaged properties must be written as stored.
2165+
if (info.isSimpleStored()) {
2166+
// @NSManaged properties end up being computed; complain if there is
2167+
// an initializer.
2168+
if (var->getParentInitializer()) {
2169+
auto &Diags = var->getASTContext().Diags;
2170+
Diags.diagnose(attr->getLocation(), diag::attr_NSManaged_initial_value)
2171+
.highlight(var->getParentInitializer()->getSourceRange());
2172+
}
2173+
2174+
// Otherwise, ok.
2175+
info = StorageImplInfo::getMutableComputed();
2176+
2177+
} else if (info.getReadImpl() == ReadImplKind::Address ||
2178+
info.getWriteImpl() == WriteImplKind::MutableAddress) {
2179+
diagnoseNotStored(/*addressed*/ 2);
2180+
} else if (info.getWriteImpl() == WriteImplKind::StoredWithObservers ||
2181+
info.getWriteImpl() == WriteImplKind::InheritedWithObservers) {
2182+
diagnoseNotStored(/*observing*/ 1);
2183+
} else {
2184+
diagnoseNotStored(/*computed*/ 0);
21202185
}
2186+
}
21212187

2122-
auto var = dyn_cast<VarDecl>(storage);
2123-
if (var == nullptr)
2124-
return;
2188+
static void finishStorageImplInfo(AbstractStorageDecl *storage,
2189+
StorageImplInfo &info) {
2190+
if (auto var = dyn_cast<VarDecl>(storage)) {
2191+
if (!info.hasStorage()) {
2192+
if (auto *init = var->getParentInitializer()) {
2193+
auto &Diags = var->getASTContext().Diags;
2194+
Diags.diagnose(init->getLoc(), diag::getset_init)
2195+
.highlight(init->getSourceRange());
2196+
}
2197+
}
21252198

2126-
if (var->getAttrs().hasAttribute<LazyAttr>()) {
2127-
finishLazyVariableImplInfo(var);
2128-
} else if (var->getAttrs().hasAttribute<NSManagedAttr>()) {
2129-
finishNSManagedImplInfo(var);
2130-
} else if (var->hasAttachedPropertyWrapper()) {
2131-
finishPropertyWrapperImplInfo(var);
2199+
if (var->getAttrs().hasAttribute<LazyAttr>()) {
2200+
finishLazyVariableImplInfo(var, info);
2201+
} else if (var->getAttrs().hasAttribute<NSManagedAttr>()) {
2202+
finishNSManagedImplInfo(var, info);
2203+
} else if (var->hasAttachedPropertyWrapper()) {
2204+
finishPropertyWrapperImplInfo(var, info);
2205+
}
21322206
}
2207+
2208+
if (isa<ProtocolDecl>(storage->getDeclContext()))
2209+
finishProtocolStorageImplInfo(storage, info);
21332210
}
21342211

21352212
static bool hasParsedAccessor(AbstractStorageDecl *storage, AccessorKind kind) {
@@ -2284,14 +2361,15 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
22842361
readWriteImpl = ReadWriteImplKind::Immutable;
22852362
}
22862363

2287-
return StorageImplInfo(readImpl, writeImpl, readWriteImpl);
2364+
StorageImplInfo info(readImpl, writeImpl, readWriteImpl);
2365+
finishStorageImplInfo(storage, info);
2366+
2367+
return info;
22882368
}
22892369

22902370
/// Try to add the appropriate accessors required a storage declaration.
22912371
/// This needs to be idempotent.
22922372
void swift::maybeAddAccessorsToStorage(AbstractStorageDecl *storage) {
2293-
finishStorageImplInfo(storage);
2294-
22952373
// Implicit properties don't get accessors.
22962374
if (storage->isImplicit() &&
22972375
!(isa<VarDecl>(storage) &&

0 commit comments

Comments
 (0)