Skip to content

Commit 66268d0

Browse files
rintarojrose-apple
authored andcommitted
[Sema] Minimum access for override method is fileprivate (#4404)
(cherry picked from commit 9a0f9d1)
1 parent 1730bff commit 66268d0

File tree

4 files changed

+45
-7
lines changed

4 files changed

+45
-7
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5544,11 +5544,12 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
55445544
std::min(classDecl->getFormalAccess(), overriddenAccess);
55455545
if (requiredAccess == Accessibility::Open && decl->isFinal())
55465546
requiredAccess = Accessibility::Public;
5547+
else if (requiredAccess == Accessibility::Private)
5548+
requiredAccess = Accessibility::FilePrivate;
55475549

55485550
bool shouldDiagnose = false;
55495551
bool shouldDiagnoseSetter = false;
5550-
if (requiredAccess > Accessibility::Private &&
5551-
!isa<ConstructorDecl>(decl)) {
5552+
if (!isa<ConstructorDecl>(decl)) {
55525553
shouldDiagnose = (decl->getFormalAccess() < requiredAccess);
55535554

55545555
if (!shouldDiagnose && matchDecl->isSettable(classDecl)) {
@@ -5558,6 +5559,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
55585559
const DeclContext *accessDC = nullptr;
55595560
if (requiredAccess == Accessibility::Internal)
55605561
accessDC = classDecl->getParentModule();
5562+
else if (requiredAccess == Accessibility::FilePrivate)
5563+
accessDC = classDecl->getDeclContext();
55615564
shouldDiagnoseSetter = ASD->isSettable(accessDC) &&
55625565
!ASD->isSetterAccessibleFrom(accessDC);
55635566
}
@@ -6498,11 +6501,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
64986501

64996502
if (CD->isRequired() && ContextTy) {
65006503
if (auto nominal = ContextTy->getAnyNominal()) {
6501-
if (CD->getFormalAccess() <
6502-
std::min(nominal->getFormalAccess(), Accessibility::Public)) {
6504+
auto requiredAccess = std::min(nominal->getFormalAccess(),
6505+
Accessibility::Public);
6506+
if (requiredAccess == Accessibility::Private)
6507+
requiredAccess = Accessibility::FilePrivate;
6508+
if (CD->getFormalAccess() < requiredAccess) {
65036509
auto diag = TC.diagnose(CD,
65046510
diag::required_initializer_not_accessible);
6505-
fixItAccessibility(diag, CD, nominal->getFormalAccess());
6511+
fixItAccessibility(diag, CD, requiredAccess);
65066512
}
65076513
}
65086514
}

test/SILGen/Inputs/mangling_private_helper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ open class Base {
55
// Demonstrate the need for a vtable entry for privateMethod().
66
// This isn't strictly necessary.
77
private class Subclass : Base {
8-
override private func privateMethod() {}
8+
override fileprivate func privateMethod() {}
99
}

test/SILOptimizer/Inputs/devirt_access_other_module.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ public func getExternalClass() -> ExternalClass {
1414
}
1515

1616
private class PrivateSubclass : ExternalClass {
17-
override private func foo() {}
17+
override fileprivate func foo() {}
1818
}

test/Sema/accessibility.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,38 @@ internal class InternalSubPrivateSet: Base {
198198
}
199199
}
200200

201+
private class PrivateSub: Base {
202+
required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=fileprivate}}
203+
private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=fileprivate}}
204+
private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
205+
get { return 0 }
206+
set {}
207+
}
208+
private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=fileprivate}}
209+
}
210+
211+
private class PrivateSubGood: Base {
212+
required fileprivate init() {}
213+
fileprivate override func foo() {}
214+
fileprivate override var bar: Int {
215+
get { return 0 }
216+
set {}
217+
}
218+
fileprivate override subscript () -> () { return () }
219+
}
220+
221+
private class PrivateSubPrivateSet: Base {
222+
required fileprivate init() {}
223+
fileprivate override func foo() {}
224+
private(set) override var bar: Int { // expected-error {{setter of overriding var must be as accessible as its enclosing type}}
225+
get { return 0 }
226+
set {}
227+
}
228+
private(set) override subscript () -> () { // okay; read-only in base class
229+
get { return () }
230+
set {}
231+
}
232+
}
201233

202234
public typealias PublicTA1 = PublicStruct
203235
public typealias PublicTA2 = InternalStruct // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}

0 commit comments

Comments
 (0)