Skip to content

Flip the switch on 'private' and 'fileprivate'. #3767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1869,11 +1869,18 @@ const DeclContext *
ValueDecl::getFormalAccessScope(const DeclContext *useDC) const {
const DeclContext *result = getDeclContext();
Accessibility access = getFormalAccess(useDC);
bool swift3PrivateChecked = false;

while (!result->isModuleScopeContext()) {
if (result->isLocalContext())
return result;

if (access == Accessibility::Private && !swift3PrivateChecked) {
if (result->getASTContext().LangOpts.EnableSwift3Private)
return result;
swift3PrivateChecked = true;
}

if (auto enclosingNominal = dyn_cast<NominalTypeDecl>(result)) {
access = std::min(access, enclosingNominal->getFormalAccess(useDC));

Expand All @@ -1895,7 +1902,6 @@ ValueDecl::getFormalAccessScope(const DeclContext *useDC) const {

switch (access) {
case Accessibility::Private:
// TODO: Implement 'private'
case Accessibility::FilePrivate:
assert(result->isModuleScopeContext());
return result;
Expand Down
5 changes: 4 additions & 1 deletion lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,12 @@ static bool checkAccessibility(const DeclContext *useDC,
if (!useDC)
return access == Accessibility::Public;

assert(sourceDC && "ValueDecl being accessed must have a valid DeclContext");
switch (access) {
case Accessibility::Private:
// TODO: Implement 'private'.
if (sourceDC->getASTContext().LangOpts.EnableSwift3Private)
return useDC == sourceDC || useDC->isChildContextOf(sourceDC);
SWIFT_FALLTHROUGH;
case Accessibility::FilePrivate:
return useDC->getModuleScopeContext() == sourceDC->getModuleScopeContext();
case Accessibility::Internal: {
Expand Down
4 changes: 3 additions & 1 deletion lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6168,7 +6168,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
const DeclContext *desiredAccessScope;
switch (AA->getAccess()) {
case Accessibility::Private:
// TODO: Implement 'private'.
assert(ED->getDeclContext()->isModuleScopeContext() &&
"non-top-level extensions make 'private' != 'fileprivate'");
SWIFT_FALLTHROUGH;
case Accessibility::FilePrivate:
desiredAccessScope = ED->getModuleScopeContext();
break;
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SDK/Foundation/IndexPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableColl
public typealias Index = Array<Int>.Index
public typealias Indices = DefaultRandomAccessIndices<IndexPath>

private var _indexes : Array<Int>
fileprivate var _indexes : Array<Int>

/// Initialize an empty index path.
public init() {
Expand Down
112 changes: 112 additions & 0 deletions test/Sema/accessibility_private.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// RUN: %target-parse-verify-swift

class Container {
private func foo() {} // expected-note * {{declared here}}
private var bar = 0 // expected-note * {{declared here}}

private struct PrivateInner {} // expected-note * {{declared here}}

func localTest() {
foo()
self.foo()

_ = bar
bar = 5
_ = self.bar
self.bar = 5

privateExtensionMethod() // FIXME expected-error {{use of unresolved identifier 'privateExtensionMethod'}}
self.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}

_ = PrivateInner()
_ = Container.PrivateInner()
}

struct Inner {
func test(obj: Container) {
obj.foo()
_ = obj.bar
obj.bar = 5
obj.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}

_ = PrivateInner()
_ = Container.PrivateInner()
}

var inner: PrivateInner? // expected-error {{property must be declared private because its type uses a private type}}
var innerQualified: Container.PrivateInner? // expected-error {{property must be declared private because its type uses a private type}}
}

var inner: PrivateInner? // expected-error {{property must be declared private because its type uses a private type}}
var innerQualified: Container.PrivateInner? // expected-error {{property must be declared private because its type uses a private type}}
}

func test(obj: Container) {
obj.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
_ = obj.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
obj.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
obj.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}

_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
}

extension Container {
private func privateExtensionMethod() {} // expected-note * {{declared here}}

func extensionTest() {
foo() // FIXME expected-error {{use of unresolved identifier 'foo'}}
self.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}

_ = bar // FIXME expected-error {{use of unresolved identifier 'bar'}}
bar = 5 // FIXME expected-error {{use of unresolved identifier 'bar'}}
_ = self.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
self.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}

privateExtensionMethod()
self.privateExtensionMethod()

_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
}

// FIXME: Why do these errors happen twice?
var extensionInner: PrivateInner? { return nil } // FIXME expected-error 2 {{use of undeclared type 'PrivateInner'}}
var extensionInnerQualified: Container.PrivateInner? { return nil } // FIXME expected-error 2 {{'PrivateInner' is not a member type of 'Container'}}
}

extension Container.Inner {
func extensionTest(obj: Container) {
obj.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}
_ = obj.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
obj.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}
obj.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}

_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
}

// FIXME: Why do these errors happen twice?
var inner: PrivateInner? { return nil } // FIXME expected-error 2 {{use of undeclared type 'PrivateInner'}}
var innerQualified: Container.PrivateInner? { return nil } // FIXME expected-error 2 {{'PrivateInner' is not a member type of 'Container'}}
}

class Sub : Container {
func subTest() {
foo() // FIXME expected-error {{use of unresolved identifier 'foo'}}
self.foo() // expected-error {{'foo' is inaccessible due to 'private' protection level}}

_ = bar // FIXME expected-error {{use of unresolved identifier 'bar'}}
bar = 5 // FIXME expected-error {{use of unresolved identifier 'bar'}}
_ = self.bar // expected-error {{'bar' is inaccessible due to 'private' protection level}}
self.bar = 5 // expected-error {{'bar' is inaccessible due to 'private' protection level}}

privateExtensionMethod() // FIXME expected-error {{use of unresolved identifier 'privateExtensionMethod'}}
self.privateExtensionMethod() // expected-error {{'privateExtensionMethod' is inaccessible due to 'private' protection level}}

_ = PrivateInner() // FIXME expected-error {{use of unresolved identifier 'PrivateInner'}}
_ = Container.PrivateInner() // expected-error {{'PrivateInner' is inaccessible due to 'private' protection level}}
}

var subInner: PrivateInner? // FIXME expected-error {{use of undeclared type 'PrivateInner'}}
var subInnerQualified: Container.PrivateInner? // FIXME expected-error {{'PrivateInner' is not a member type of 'Container'}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ struct Curds {
}

private class Butter {
private func churn<T>(block: () throws -> T) throws -> T {
fileprivate func churn<T>(block: () throws -> T) throws -> T {
return try block()
}
}
Expand Down