@@ -1392,7 +1392,7 @@ synthesizeTrivialGetterBody(AccessorDecl *getter, TargetImpl target,
1392
1392
/// underlying storage.
1393
1393
static std::pair<BraceStmt *, bool>
1394
1394
synthesizeTrivialGetterBody(AccessorDecl *getter, ASTContext &ctx) {
1395
- assert(getter->getStorage()->hasStorage());
1395
+ assert(getter->getStorage()->getImplInfo(). hasStorage());
1396
1396
return synthesizeTrivialGetterBody(getter, TargetImpl::Storage, ctx);
1397
1397
}
1398
1398
@@ -3431,6 +3431,73 @@ static StorageImplInfo classifyWithHasStorageAttr(VarDecl *var) {
3431
3431
return StorageImplInfo(ReadImplKind::Stored, writeImpl, readWriteImpl);
3432
3432
}
3433
3433
3434
+ bool HasStorageRequest::evaluate(Evaluator &evaluator,
3435
+ AbstractStorageDecl *storage) const {
3436
+ // Parameters are always stored.
3437
+ if (isa<ParamDecl>(storage))
3438
+ return true;
3439
+
3440
+ // Only variables can be stored.
3441
+ auto *var = dyn_cast<VarDecl>(storage);
3442
+ if (!var)
3443
+ return false;
3444
+
3445
+ // @_hasStorage implies that it... has storage.
3446
+ if (var->getAttrs().hasAttribute<HasStorageAttr>())
3447
+ return true;
3448
+
3449
+ // Protocol requirements never have storage.
3450
+ if (isa<ProtocolDecl>(storage->getDeclContext()))
3451
+ return false;
3452
+
3453
+ // lazy declarations do not have storage.
3454
+ if (storage->getAttrs().hasAttribute<LazyAttr>())
3455
+ return false;
3456
+
3457
+ // @NSManaged attributes don't have storage
3458
+ if (storage->getAttrs().hasAttribute<NSManagedAttr>())
3459
+ return false;
3460
+
3461
+ // Any accessors that read or write imply that there is no storage.
3462
+ if (storage->getParsedAccessor(AccessorKind::Get) ||
3463
+ storage->getParsedAccessor(AccessorKind::Read) ||
3464
+ storage->getParsedAccessor(AccessorKind::Address) ||
3465
+ storage->getParsedAccessor(AccessorKind::Set) ||
3466
+ storage->getParsedAccessor(AccessorKind::Modify) ||
3467
+ storage->getParsedAccessor(AccessorKind::MutableAddress))
3468
+ return false;
3469
+
3470
+ // willSet or didSet in an overriding property imply that there is no storage.
3471
+ if ((storage->getParsedAccessor(AccessorKind::WillSet) ||
3472
+ storage->getParsedAccessor(AccessorKind::DidSet)) &&
3473
+ storage->getAttrs().hasAttribute<OverrideAttr>())
3474
+ return false;
3475
+
3476
+ // The presence of a property wrapper implies that there is no storage.
3477
+ if (var->hasAttachedPropertyWrapper())
3478
+ return false;
3479
+
3480
+ // Look for any accessor macros that might make this property computed.
3481
+ bool hasStorage = true;
3482
+ namelookup::forEachPotentialAttachedMacro(
3483
+ var, MacroRole::Accessor,
3484
+ [&](MacroDecl *macro, const MacroRoleAttr *attr) {
3485
+ // Will this macro introduce observers?
3486
+ bool foundObserver = accessorMacroOnlyIntroducesObservers(macro, attr);
3487
+
3488
+ // If it's not (just) introducing observers, it's making the property
3489
+ // computed.
3490
+ if (!foundObserver)
3491
+ hasStorage = false;
3492
+
3493
+ // If it will introduce observers, and there is an "override",
3494
+ // the property doesn't have storage.
3495
+ if (foundObserver && storage->getAttrs().hasAttribute<OverrideAttr>())
3496
+ hasStorage = false;
3497
+ });
3498
+ return hasStorage;
3499
+ }
3500
+
3434
3501
StorageImplInfo
3435
3502
StorageImplInfoRequest::evaluate(Evaluator &evaluator,
3436
3503
AbstractStorageDecl *storage) const {
@@ -3590,6 +3657,8 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
3590
3657
StorageImplInfo info(readImpl, writeImpl, readWriteImpl);
3591
3658
finishStorageImplInfo(storage, info);
3592
3659
3660
+ assert(info.hasStorage() == storage->hasStorage() ||
3661
+ storage->getASTContext().Diags.hadAnyError());
3593
3662
return info;
3594
3663
}
3595
3664
0 commit comments