Skip to content

Commit 9117c57

Browse files
committed
Allow inheritance from resilient classes with missing members
When a class has missing vtable entries, we don’t allow it to be subclassed. This is unnecessarily restrictive for resilient classes, and @_implementationOnly imports now make missing vtable entries much more common. This commit carves out an exception to that rule for resilient classes. Fixes <rdar://problem/50902125>.
1 parent 64ce7b9 commit 9117c57

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

Diff for: lib/Sema/TypeCheckDecl.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -2958,7 +2958,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
29582958
break;
29592959
}
29602960

2961-
if (!isInvalidSuperclass && Super->hasMissingVTableEntries()) {
2961+
if (!isInvalidSuperclass && Super->hasMissingVTableEntries() &&
2962+
!Super->isResilient(CD->getParentModule(),
2963+
ResilienceExpansion::Minimal)) {
29622964
auto *superFile = Super->getModuleScopeContext();
29632965
if (auto *serialized = dyn_cast<SerializedASTFile>(superFile)) {
29642966
if (serialized->getLanguageVersionBuiltWith() !=

Diff for: test/decl/class/override-implementationOnly.swift

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// For convenience, this file includes the three different "files" used in this
4+
// test. It selects one with -DCoreDishwasher, -DDishwasherKit, or neither.
5+
6+
// RUN: %target-swift-frontend -emit-module %s -DCoreDishwasher -module-name CoreDishwasher -o %t/CoreDishwasher -emit-module-path %t/CoreDishwasher.swiftmodule -I %t
7+
// RUN: %target-swift-frontend -emit-module %s -DDishwasherKit -module-name DishwasherKit -o %t/DishwasherKit -emit-module-path %t/DishwasherKit.swiftmodule -enable-library-evolution -I %t
8+
// RUN: %target-typecheck-verify-swift -I %t
9+
10+
#if CoreDishwasher
11+
12+
public struct SpimsterWicket {
13+
public init() {}
14+
}
15+
16+
#elseif DishwasherKit
17+
18+
@_implementationOnly import CoreDishwasher
19+
20+
open class Dishwasher {
21+
public init() {}
22+
23+
var wicket = SpimsterWicket()
24+
25+
open var modelName: String { "Dishwasher" }
26+
}
27+
28+
open class NoUserServiceablePartsInside {
29+
public init() {}
30+
internal init(wicket: SpimsterWicket) {}
31+
public convenience init(inconvenient: ()) {
32+
self.init()
33+
}
34+
}
35+
36+
#else
37+
38+
import DishwasherKit
39+
40+
class FancyDishwasher: Dishwasher {
41+
override var modelName: String { "Fancy \(super.modelName)" }
42+
}
43+
44+
class VoidedWarranty: NoUserServiceablePartsInside {
45+
override init() { super.init() }
46+
}
47+
48+
// FIXME: This diagnostic should be better, but it matches what we're already
49+
// doing for disallowed convenience inits.
50+
let notAllowed = VoidedWarranty(inconvenient: ()) // expected-error{{argument passed to call that takes no arguments}}
51+
52+
#endif

0 commit comments

Comments
 (0)