Skip to content

Commit 9f3ff04

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 8b7ad4d + 629766e commit 9f3ff04

File tree

6 files changed

+37
-68
lines changed

6 files changed

+37
-68
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7190,8 +7190,7 @@ inline bool Decl::isPotentiallyOverridable() const {
71907190
isa<SubscriptDecl>(this) ||
71917191
isa<FuncDecl>(this) ||
71927192
isa<DestructorDecl>(this)) {
7193-
return getDeclContext()->getSelfClassDecl() ||
7194-
isa<ProtocolDecl>(getDeclContext());
7193+
return getDeclContext()->getSelfClassDecl();
71957194
} else {
71967195
return false;
71977196
}

lib/AST/TypeCheckRequests.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ void IsFinalRequest::cacheResult(bool value) const {
257257
decl->LazySemanticInfo.isFinalComputed = true;
258258
decl->LazySemanticInfo.isFinal = value;
259259

260-
// Register Final in attributes, to preserve print order
260+
// Add an attribute for printing
261261
if (value && !decl->getAttrs().hasAttribute<FinalAttr>())
262262
decl->getAttrs().add(new (decl->getASTContext()) FinalAttr(/*Implicit=*/true));
263263
}
@@ -289,6 +289,10 @@ Optional<bool> IsDynamicRequest::getCachedResult() const {
289289
void IsDynamicRequest::cacheResult(bool value) const {
290290
auto decl = std::get<0>(getStorage());
291291
decl->setIsDynamic(value);
292+
293+
// Add an attribute for printing
294+
if (value && !decl->getAttrs().hasAttribute<DynamicAttr>())
295+
decl->getAttrs().add(new (decl->getASTContext()) DynamicAttr(/*Implicit=*/true));
292296
}
293297

294298
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckDecl.cpp

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,31 +1099,10 @@ static bool inferFinalAndDiagnoseIfNeeded(ValueDecl *D, ClassDecl *cls,
10991099
return true;
11001100
}
11011101

1102-
/// Make the given declaration 'dynamic', if it isn't already marked as such.
1103-
static void makeDynamic(ValueDecl *decl) {
1104-
// If there isn't already a 'dynamic' attribute, add an inferred one.
1105-
if (decl->getAttrs().hasAttribute<DynamicAttr>())
1106-
return;
1107-
1108-
auto attr = new (decl->getASTContext()) DynamicAttr(/*implicit=*/true);
1109-
decl->getAttrs().add(attr);
1110-
}
1111-
1112-
static llvm::Expected<bool> isStorageDynamic(Evaluator &evaluator,
1113-
AccessorDecl *accessor) {
1114-
auto isDynamicResult = evaluator(IsDynamicRequest{accessor->getStorage()});
1115-
1116-
if (!isDynamicResult)
1117-
return isDynamicResult;
1118-
1119-
return *isDynamicResult;
1120-
}
1121-
11221102
/// Runtime-replacable accessors are dynamic when their storage declaration
11231103
/// is dynamic and they were explicitly defined or they are implicitly defined
11241104
/// getter/setter because no accessor was defined.
1125-
static llvm::Expected<bool>
1126-
doesAccessorNeedDynamicAttribute(AccessorDecl *accessor, Evaluator &evaluator) {
1105+
static bool doesAccessorNeedDynamicAttribute(AccessorDecl *accessor) {
11271106
auto kind = accessor->getAccessorKind();
11281107
auto storage = accessor->getStorage();
11291108
bool isObjC = storage->isObjC();
@@ -1134,40 +1113,40 @@ doesAccessorNeedDynamicAttribute(AccessorDecl *accessor, Evaluator &evaluator) {
11341113
if (!isObjC &&
11351114
(readImpl == ReadImplKind::Read || readImpl == ReadImplKind::Address))
11361115
return false;
1137-
return isStorageDynamic(evaluator, accessor);
1116+
return storage->isDynamic();
11381117
}
11391118
case AccessorKind::Set: {
11401119
auto writeImpl = storage->getWriteImpl();
11411120
if (!isObjC && (writeImpl == WriteImplKind::Modify ||
11421121
writeImpl == WriteImplKind::MutableAddress ||
11431122
writeImpl == WriteImplKind::StoredWithObservers))
11441123
return false;
1145-
return isStorageDynamic(evaluator, accessor);
1124+
return storage->isDynamic();
11461125
}
11471126
case AccessorKind::Read:
11481127
if (!isObjC && storage->getReadImpl() == ReadImplKind::Read)
1149-
return isStorageDynamic(evaluator, accessor);
1128+
return storage->isDynamic();
11501129
return false;
11511130
case AccessorKind::Modify: {
11521131
if (!isObjC && storage->getWriteImpl() == WriteImplKind::Modify)
1153-
return isStorageDynamic(evaluator, accessor);
1132+
return storage->isDynamic();
11541133
return false;
11551134
}
11561135
case AccessorKind::MutableAddress: {
11571136
if (!isObjC && storage->getWriteImpl() == WriteImplKind::MutableAddress)
1158-
return isStorageDynamic(evaluator, accessor);
1137+
return storage->isDynamic();
11591138
return false;
11601139
}
11611140
case AccessorKind::Address: {
11621141
if (!isObjC && storage->getReadImpl() == ReadImplKind::Address)
1163-
return isStorageDynamic(evaluator, accessor);
1142+
return storage->isDynamic();
11641143
return false;
11651144
}
11661145
case AccessorKind::DidSet:
11671146
case AccessorKind::WillSet:
11681147
if (!isObjC &&
11691148
storage->getWriteImpl() == WriteImplKind::StoredWithObservers)
1170-
return isStorageDynamic(evaluator, accessor);
1149+
return storage->isDynamic();
11711150
return false;
11721151
}
11731152
llvm_unreachable("covered switch");
@@ -1284,40 +1263,17 @@ IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
12841263
}
12851264

12861265
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
1287-
// Swift 5: Runtime-replacable accessors are dynamic when their storage declaration
1266+
// Runtime-replacable accessors are dynamic when their storage declaration
12881267
// is dynamic and they were explicitly defined or they are implicitly defined
12891268
// getter/setter because no accessor was defined.
1290-
if (decl->getASTContext().LangOpts.isSwiftVersionAtLeast(5))
1291-
return doesAccessorNeedDynamicAttribute(accessor, evaluator);
1292-
1293-
// Pre Swift 5: Runtime-replacable accessors are dynamic when their storage declaration
1294-
// is dynamic. Other accessors are never dynamic.
1295-
switch (accessor->getAccessorKind()) {
1296-
case AccessorKind::Get:
1297-
case AccessorKind::Set: {
1298-
auto isDynamicResult = evaluator(
1299-
IsDynamicRequest{accessor->getStorage()});
1300-
if (isDynamicResult && *isDynamicResult)
1301-
makeDynamic(decl);
1302-
1303-
return isDynamicResult;
1304-
}
1305-
1306-
#define OBJC_ACCESSOR(ID, KEYWORD)
1307-
#define ACCESSOR(ID) \
1308-
case AccessorKind::ID:
1309-
#include "swift/AST/AccessorKinds.def"
1310-
return false;
1311-
}
1269+
return doesAccessorNeedDynamicAttribute(accessor);
13121270
}
13131271

13141272
// The 'NSManaged' attribute implies 'dynamic'.
13151273
// FIXME: Use a semantic check for NSManaged rather than looking for the
13161274
// attribute (which could be ill-formed).
1317-
if (decl->getAttrs().hasAttribute<NSManagedAttr>()) {
1318-
makeDynamic(decl);
1275+
if (decl->getAttrs().hasAttribute<NSManagedAttr>())
13191276
return true;
1320-
}
13211277

13221278
// The presence of 'final' blocks the inference of 'dynamic'.
13231279
if (decl->isFinal())
@@ -1334,10 +1290,8 @@ IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
13341290
// @objc declarations in class extensions are implicitly dynamic.
13351291
// This is intended to enable overriding the declarations.
13361292
auto dc = decl->getDeclContext();
1337-
if (isa<ExtensionDecl>(dc) && dc->getSelfClassDecl()) {
1338-
makeDynamic(decl);
1293+
if (isa<ExtensionDecl>(dc) && dc->getSelfClassDecl())
13391294
return true;
1340-
}
13411295

13421296
// If any of the declarations overridden by this declaration are dynamic
13431297
// or were imported from Objective-C, this declaration is dynamic.
@@ -1347,10 +1301,8 @@ IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
13471301
auto overriddenDecls = evaluateOrDefault(evaluator,
13481302
OverriddenDeclsRequest{decl}, {});
13491303
for (auto overridden : overriddenDecls) {
1350-
if (overridden->isDynamic() || overridden->hasClangNode()) {
1351-
makeDynamic(decl);
1304+
if (overridden->isDynamic() || overridden->hasClangNode())
13521305
return true;
1353-
}
13541306
}
13551307

13561308
return false;

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,14 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
831831
if (ctx.isAccessControlDisabled())
832832
return;
833833

834+
if (isa<ProtocolDecl>(decl->getDeclContext()))
835+
return;
836+
834837
auto &diags = ctx.Diags;
835838

836839
auto dc = decl->getDeclContext();
837840
auto classDecl = dc->getSelfClassDecl();
841+
assert(classDecl != nullptr && "Should have ruled out protocols above");
838842

839843
bool isAccessor = isa<AccessorDecl>(decl);
840844

@@ -851,8 +855,7 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
851855
if (!isAccessor &&
852856
!baseHasOpenAccess &&
853857
baseDecl->getModuleContext() != decl->getModuleContext() &&
854-
!isa<ConstructorDecl>(decl) &&
855-
!isa<ProtocolDecl>(decl->getDeclContext())) {
858+
!isa<ConstructorDecl>(decl)) {
856859
// NSObject.hashValue was made non-overridable in Swift 5; one should
857860
// override NSObject.hash instead.
858861
if (isNSObjectHashValue(baseDecl)) {
@@ -875,8 +878,7 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
875878
}
876879
diags.diagnose(baseDecl, diag::overridden_here);
877880

878-
} else if (!isa<ConstructorDecl>(decl) &&
879-
!isa<ProtocolDecl>(decl->getDeclContext())) {
881+
} else if (!isa<ConstructorDecl>(decl)) {
880882
auto matchAccessScope =
881883
baseDecl->getFormalAccessScope(dc);
882884
auto classAccessScope =
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
protocol Base {
2+
var foo: String { get }
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module-path %t/other.swiftmodule %S/Inputs/protocol-override-other.swift -module-name other -enable-testing
3+
// RUN: %target-swift-frontend -typecheck %s -I %t
4+
5+
@testable import other
6+
7+
protocol Sub : Base {
8+
var foo: String { get set }
9+
}

0 commit comments

Comments
 (0)