Skip to content

Commit da80c42

Browse files
committed
Sema: Don't infer 'dynamic' for static methods and properties
Otherwise, can crash in the AST verifier. Fixes <rdar://problem/32862136>.
1 parent c34d269 commit da80c42

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,12 +1245,14 @@ static void validatePatternBindingEntries(TypeChecker &tc,
12451245

12461246
void swift::makeFinal(ASTContext &ctx, ValueDecl *D) {
12471247
if (D && !D->isFinal()) {
1248+
assert(!D->isDynamic());
12481249
D->getAttrs().add(new (ctx) FinalAttr(/*IsImplicit=*/true));
12491250
}
12501251
}
12511252

12521253
void swift::makeDynamic(ASTContext &ctx, ValueDecl *D) {
12531254
if (D && !D->isDynamic()) {
1255+
assert(!D->isFinal());
12541256
D->getAttrs().add(new (ctx) DynamicAttr(/*IsImplicit=*/true));
12551257
}
12561258
}
@@ -2556,15 +2558,29 @@ static void inferDynamic(ASTContext &ctx, ValueDecl *D) {
25562558

25572559
// Variables declared with 'let' cannot be 'dynamic'.
25582560
if (auto VD = dyn_cast<VarDecl>(D)) {
2559-
if (VD->isLet() && !isNSManaged) return;
2561+
auto staticSpelling = VD->getParentPatternBinding()->getStaticSpelling();
2562+
2563+
// The presence of 'static' bocks the inference of 'dynamic'.
2564+
if (VD->isStatic() && staticSpelling == StaticSpellingKind::KeywordStatic)
2565+
return;
2566+
2567+
if (VD->isLet() && !isNSManaged)
2568+
return;
25602569
}
25612570

25622571
// Accessors should not infer 'dynamic' on their own; they can get it from
25632572
// their storage decls.
2564-
if (auto FD = dyn_cast<FuncDecl>(D))
2573+
if (auto FD = dyn_cast<FuncDecl>(D)) {
25652574
if (FD->isAccessor())
25662575
return;
25672576

2577+
auto staticSpelling = FD->getStaticSpelling();
2578+
2579+
// The presence of 'static' bocks the inference of 'dynamic'.
2580+
if (FD->isStatic() && staticSpelling == StaticSpellingKind::KeywordStatic)
2581+
return;
2582+
}
2583+
25682584
// The presence of 'final' on a class prevents 'dynamic'.
25692585
auto classDecl = D->getDeclContext()->getAsClassOrClassExtensionContext();
25702586
if (!classDecl) return;
@@ -5176,8 +5192,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
51765192

51775193
// If the storage is dynamic or final, propagate to this accessor.
51785194
if (isObjC &&
5179-
storage->isDynamic() &&
5180-
!storage->isFinal())
5195+
storage->isDynamic())
51815196
makeDynamic(TC.Context, FD);
51825197

51835198
if (storage->isFinal())

test/attr/attr_dynamic_infer.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ extension Sub {
5959
@objc class FinalTests {}
6060

6161
extension FinalTests {
62-
// CHECK: @objc final func foo
62+
// CHECK: @objc final func foo
6363
final func foo() { }
6464

6565
// CHECK: @objc final var prop: Super
@@ -77,5 +77,11 @@ extension FinalTests {
7777
// CHECK: @objc final set
7878
set { }
7979
}
80+
81+
// CHECK: static @objc var x
82+
static var x: Int = 0
83+
84+
// CHECK: @objc static func bar
85+
static func bar() { }
8086
}
8187

0 commit comments

Comments
 (0)