-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathaccessibility.swift
179 lines (142 loc) · 8.25 KB
/
accessibility.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// RUN: %empty-directory(%t)
// RUN: cp %s %t/main.swift
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/has_accessibility.swift -D DEFINE_VAR_FOR_SCOPED_IMPORT -enable-testing
// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/Inputs/accessibility_other.swift -module-name accessibility -I %t -sdk "" -enable-access-control -verify -verify-ignore-unknown
// RUN: %target-swift-frontend -typecheck -primary-file %t/main.swift %S/Inputs/accessibility_other.swift -module-name accessibility -I %t -sdk "" -disable-access-control -D ACCESS_DISABLED
// RUN: not %target-swift-frontend -typecheck -primary-file %t/main.swift %S/Inputs/accessibility_other.swift -module-name accessibility -I %t -sdk "" -D TESTABLE 2>&1 | %FileCheck -check-prefix=TESTABLE %s
#if TESTABLE
@testable import has_accessibility
#else
import has_accessibility
#endif
// This deliberately has the wrong import kind.
import var has_accessibility.zz // expected-error {{variable 'zz' does not exist in module 'has_accessibility'}}
func markUsed<T>(_ t: T) {}
markUsed(has_accessibility.x)
markUsed(has_accessibility.y) // expected-error {{module 'has_accessibility' has no member named 'y'}}
markUsed(has_accessibility.z) // expected-error {{module 'has_accessibility' has no member named 'z'}}
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE: :[[@LINE-3]]:10: error: module 'has_accessibility' has no member named 'z'
markUsed(accessibility.a)
markUsed(accessibility.b)
markUsed(accessibility.c) // expected-error {{'c' is inaccessible due to 'private' protection level}}
markUsed(x)
markUsed(y) // expected-error {{cannot find 'y' in scope}}
markUsed(z) // expected-error {{cannot find 'z' in scope}}
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE: :[[@LINE-3]]:10: error: cannot find 'z' in scope
markUsed(a)
markUsed(b)
markUsed(c) // expected-error {{cannot find 'c' in scope}}
Foo.x()
Foo.y() // expected-error {{'y' is inaccessible due to 'internal' protection level}}
Foo.z() // expected-error {{'z' is inaccessible due to 'private' protection level}}
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE: :[[@LINE-3]]:{{[^:]+}}: error: 'z' is inaccessible due to 'private' protection level
Foo.a()
Foo.b()
Foo.c() // expected-error {{'c' is inaccessible due to 'private' protection level}}
_ = Foo() // expected-error {{'Foo' initializer is inaccessible due to 'internal' protection level}}
// <rdar://problem/27982012> QoI: Poor diagnostic for inaccessible initializer
struct rdar27982012 {
var x: Int
private init(_ x: Int) { self.x = x } // expected-note {{'init(_:)' declared here}}
}
_ = { rdar27982012($0.0) }((1, 2)) // expected-error {{initializer is inaccessible due to 'private' protection level}}
// TESTABLE-NOT: :[[@LINE-1]]:{{[^:]+}}:
_ = PrivateInit() // expected-error {{'PrivateInit' initializer is inaccessible due to 'private' protection level}}
// TESTABLE: :[[@LINE-1]]:{{[^:]+}}: error: 'PrivateInit' initializer is inaccessible due to 'private' protection level
var s = StructWithPrivateSetter()
// expected-note@-1 3{{did you mean 's'?}}
s.x = 42 // expected-error {{cannot assign to property: 'x' setter is inaccessible}}
class Sub : Base {
func test() {
value = 4 // expected-error {{cannot assign to property: 'value' setter is inaccessible}}
self.value = 4 // expected-error {{cannot assign to property: 'value' setter is inaccessible}}
super.value = 4 // expected-error {{cannot assign to property: 'value' setter is inaccessible}}
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
self.method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
super.method() // expected-error {{'method' is inaccessible due to 'internal' protection level}}
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
// TESTABLE-NOT: :[[@LINE-3]]:{{[^:]+}}:
}
}
class ObservingOverrider : Base {
override var value: Int { // expected-error {{cannot observe read-only property 'value'; it can't change}}
willSet { markUsed(newValue) }
}
}
class ReplacingOverrider : Base {
override var value: Int {
get { return super.value }
set { super.value = newValue } // expected-error {{cannot assign to property: 'value' setter is inaccessible}}
}
}
protocol MethodProto {
func method() // expected-note * {{protocol requires function 'method()' with type '() -> ()'}}
}
extension OriginallyEmpty : MethodProto {}
#if !ACCESS_DISABLED
extension HiddenMethod : MethodProto {} // expected-error {{type 'HiddenMethod' does not conform to protocol 'MethodProto'}} expected-note {{add stubs for conformance}}
// TESTABLE-NOT: :[[@LINE-1]]:{{[^:]+}}:
extension Foo : MethodProto {} // expected-error {{type 'Foo' does not conform to protocol 'MethodProto'}} expected-note {{add stubs for conformance}}
#endif
protocol TypeProto {
associatedtype TheType // expected-note * {{protocol requires nested type 'TheType'}}
}
extension OriginallyEmpty {}
#if !ACCESS_DISABLED
extension HiddenType : TypeProto {} // expected-error {{type 'HiddenType' does not conform to protocol 'TypeProto'}} expected-note {{add stubs for conformance}}
// TESTABLE-NOT: :[[@LINE-1]]:{{[^:]+}}:
extension Foo : TypeProto {} // expected-error {{type 'Foo' does not conform to protocol 'TypeProto'}} expected-note {{add stubs for conformance}}
#endif
#if !ACCESS_DISABLED
private func privateInBothFiles() {} // no-warning
private func privateInPrimaryFile() {} // expected-error {{invalid redeclaration}}
func privateInOtherFile() {}
#endif
#if !ACCESS_DISABLED
struct ConformerByTypeAlias : TypeProto {
private typealias TheType = Int // expected-error {{type alias 'TheType' must be declared internal because it matches a requirement in internal protocol 'TypeProto'}} {{none}}
// expected-note@-1 {{mark the type alias as 'internal' to satisfy the requirement}} {{3-10=internal}}
}
struct ConformerByLocalType : TypeProto {
private struct TheType {} // expected-error {{struct 'TheType' must be declared internal because it matches a requirement in internal protocol 'TypeProto'}} {{none}}
// expected-note@-1 {{mark the struct as 'internal' to satisfy the requirement}} {{3-10=internal}}
}
private struct PrivateConformerByLocalType : TypeProto {
struct TheType {} // okay
}
private struct PrivateConformerByLocalTypeBad : TypeProto {
private struct TheType {} // expected-error {{struct 'TheType' must be as accessible as its enclosing type because it matches a requirement in protocol 'TypeProto'}} {{none}}
// expected-note@-1 {{mark the struct as 'fileprivate' to satisfy the requirement}} {{3-10=fileprivate}}
}
#endif
public protocol Fooable {
func foo() // expected-note * {{protocol requires function 'foo()'}}
}
#if !ACCESS_DISABLED
internal struct FooImpl: Fooable, HasDefaultImplementation {} // expected-error {{type 'FooImpl' does not conform to protocol 'Fooable'}} expected-note {{add stubs for conformance}}
public struct PublicFooImpl: Fooable, HasDefaultImplementation {} // expected-error {{type 'PublicFooImpl' does not conform to protocol 'Fooable'}} expected-note {{add stubs for conformance}}
// TESTABLE-NOT: method 'foo()'
internal class TestableSub: InternalBase {} // expected-error {{cannot find type 'InternalBase' in scope}}
public class TestablePublicSub: InternalBase {} // expected-error {{cannot find type 'InternalBase' in scope}}
// TESTABLE-NOT: cannot find type 'InternalBase' in scope
#endif
// FIXME: Remove -verify-ignore-unknown.
// <unknown>:0: error: unexpected note produced: 'y' declared here
// <unknown>:0: error: unexpected note produced: 'z' declared here
// <unknown>:0: error: unexpected note produced: 'init()' declared here
// <unknown>:0: error: unexpected note produced: 'method()' declared here
// <unknown>:0: error: unexpected note produced: 'method' declared here
// <unknown>:0: error: unexpected note produced: 'method' declared here
class AccessMemberOfInternalProtocol : ImplementsInternalProtocol {
func testProperty() { let _ = i } // expected-error {{'i' is inaccessible due to 'internal' protection level}}
}