Skip to content

Commit bab6518

Browse files
committed
Sema: Add a test for accessor availability diagnostics.
This test documents the current behavior of availability diagnostics for generalized accessors, including some bugs which have been called out as FIXMEs.
1 parent c96803f commit bab6518

File tree

1 file changed

+253
-0
lines changed

1 file changed

+253
-0
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -module-name MyModule
2+
3+
struct Value {
4+
static let defaultValue = Value(a: Nested(b: 1))
5+
6+
struct Nested {
7+
var b: Int
8+
9+
@discardableResult
10+
mutating func setToZero() -> Int {
11+
let prev = b
12+
b = 0
13+
return prev
14+
}
15+
}
16+
17+
var a: Nested
18+
19+
subscript(_ i: Int) -> Nested {
20+
get { a }
21+
set { a = newValue }
22+
}
23+
24+
@discardableResult
25+
mutating func setToZero() -> Int {
26+
let prev = a.b
27+
a.setToZero()
28+
return prev
29+
}
30+
}
31+
32+
struct BaseStruct {
33+
var available: Value = .defaultValue
34+
35+
var unavailableGetter: Value {
36+
@available(*, unavailable)
37+
get { fatalError() } // expected-note 24 {{getter for 'unavailableGetter' has been explicitly marked unavailable here}}
38+
set {}
39+
}
40+
41+
var unavailableSetter: Value {
42+
get { .defaultValue }
43+
@available(*, unavailable)
44+
set { fatalError() } // expected-note 16 {{setter for 'unavailableSetter' has been explicitly marked unavailable here}}
45+
}
46+
47+
var unavailableGetterAndSetter: Value {
48+
@available(*, unavailable)
49+
get { fatalError() } // expected-note 24 {{getter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}}
50+
@available(*, unavailable)
51+
set { fatalError() } // expected-note 16 {{setter for 'unavailableGetterAndSetter' has been explicitly marked unavailable here}}
52+
}
53+
}
54+
55+
func takesIntInOut(_ i: inout Int) -> Int {
56+
return 0
57+
}
58+
59+
let someValue = Value.defaultValue
60+
61+
func testRValueLoads() {
62+
var x = BaseStruct() // expected-warning {{variable 'x' was never mutated; consider changing to 'let' constant}}
63+
64+
_ = x.available
65+
_ = x.available.a
66+
_ = x.available[0]
67+
_ = x.available[0].b
68+
69+
_ = x.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}}
70+
_ = x.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
71+
_ = x.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}}
72+
_ = x.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}}
73+
74+
_ = x.unavailableSetter
75+
_ = x.unavailableSetter.a
76+
_ = x.unavailableSetter[0] // expected-error {{setter for 'unavailableSetter' is unavailable}} FIXME: setter should not be diagnosed
77+
_ = x.unavailableSetter[0].b // expected-error {{setter for 'unavailableSetter' is unavailable}} FIXME: setter should not be diagnosed
78+
79+
_ = x.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
80+
_ = x.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
81+
_ = x.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} FIXME: setter should not be diagnosed
82+
_ = x.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} FIXME: setter should not be diagnosed
83+
}
84+
85+
func testLValueAssignments() {
86+
var x = BaseStruct()
87+
88+
x.available = someValue
89+
x.available.a = someValue.a
90+
x.available[0] = someValue.a
91+
x.available[0].b = 1
92+
93+
x.unavailableGetter = someValue
94+
x.unavailableGetter.a = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
95+
x.unavailableGetter[0] = someValue.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
96+
x.unavailableGetter[0].b = 1 // expected-error {{getter for 'unavailableGetter' is unavailable}}
97+
98+
x.unavailableSetter = someValue // expected-error {{setter for 'unavailableSetter' is unavailable}}
99+
x.unavailableSetter.a = someValue.a // FIXME: missing diagnostic for setter
100+
x.unavailableSetter[0] = someValue.a // expected-error {{setter for 'unavailableSetter' is unavailable}}
101+
x.unavailableSetter[0].b = 1 // expected-error {{setter for 'unavailableSetter' is unavailable}}
102+
103+
x.unavailableGetterAndSetter = someValue // expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
104+
x.unavailableGetterAndSetter.a = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter
105+
x.unavailableGetterAndSetter[0] = someValue.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
106+
x.unavailableGetterAndSetter[0].b = 1 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
107+
}
108+
109+
func testKeyPathLoads() {
110+
let a = [0]
111+
var x = BaseStruct()
112+
113+
_ = x[keyPath: \.available]
114+
_ = x[keyPath: \.available.a]
115+
_ = x[keyPath: \.available[0]]
116+
_ = x[keyPath: \.available[0].b]
117+
_ = a[keyPath: \.[takesIntInOut(&x.available.a.b)]]
118+
_ = a[keyPath: \.[takesIntInOut(&x.available[0].b)]]
119+
120+
_ = x[keyPath: \.unavailableGetter] // FIXME: missing diagnostic for getter
121+
_ = x[keyPath: \.unavailableGetter.a] // FIXME: missing diagnostic for getter
122+
_ = x[keyPath: \.unavailableGetter[0]] // FIXME: missing diagnostic for getter
123+
_ = x[keyPath: \.unavailableGetter[0].b] // FIXME: missing diagnostic for getter
124+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetter.a.b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
125+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetter[0].b)]] // expected-error {{getter for 'unavailableGetter' is unavailable}}
126+
127+
_ = x[keyPath: \.unavailableSetter]
128+
_ = x[keyPath: \.unavailableSetter.a]
129+
_ = x[keyPath: \.unavailableSetter[0]]
130+
_ = x[keyPath: \.unavailableSetter[0].b]
131+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableSetter.a.b)]] // FIXME: missing diagnostic for setter
132+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableSetter[0].b)]] // expected-error {{setter for 'unavailableSetter' is unavailable}}
133+
134+
_ = x[keyPath: \.unavailableGetterAndSetter] // FIXME: missing diagnostic for getter
135+
_ = x[keyPath: \.unavailableGetterAndSetter.a] // FIXME: missing diagnostic for getter
136+
_ = x[keyPath: \.unavailableGetterAndSetter[0]] // FIXME: missing diagnostic for getter
137+
_ = x[keyPath: \.unavailableGetterAndSetter[0].b] // FIXME: missing diagnostic for getter
138+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter.a.b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter
139+
_ = a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter[0].b)]] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
140+
}
141+
142+
func testKeyPathAssignments() {
143+
var a = [0]
144+
var x = BaseStruct()
145+
146+
x[keyPath: \.available] = someValue
147+
x[keyPath: \.available.a] = someValue.a
148+
x[keyPath: \.available[0]] = someValue.a
149+
x[keyPath: \.available[0].b] = 1
150+
x[keyPath: \.available] = someValue
151+
a[keyPath: \.[takesIntInOut(&x.available.a.b)]] = 0
152+
a[keyPath: \.[takesIntInOut(&x.available[0].b)]] = 0
153+
154+
x[keyPath: \.unavailableGetter] = someValue
155+
x[keyPath: \.unavailableGetter.a] = someValue.a // FIXME: missing diagnostic for getter
156+
x[keyPath: \.unavailableGetter[0]] = someValue.a // FIXME: missing diagnostic for getter
157+
x[keyPath: \.unavailableGetter[0].b] = 1 // FIXME: missing diagnostic for getter
158+
a[keyPath: \.[takesIntInOut(&x.unavailableGetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
159+
a[keyPath: \.[takesIntInOut(&x.unavailableGetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetter' is unavailable}}
160+
161+
x[keyPath: \.unavailableSetter] = someValue
162+
x[keyPath: \.unavailableSetter.a] = someValue.a // FIXME: missing diagnostic for setter
163+
x[keyPath: \.unavailableSetter[0]] = someValue.a // FIXME: missing diagnostic for setter
164+
x[keyPath: \.unavailableSetter[0].b] = 1 // FIXME: missing diagnostic for setter
165+
a[keyPath: \.[takesIntInOut(&x.unavailableSetter.a.b)]] = 0 // FIXME: missing diagnostic for setter
166+
a[keyPath: \.[takesIntInOut(&x.unavailableSetter[0].b)]] = 0 // expected-error {{setter for 'unavailableSetter' is unavailable}}
167+
168+
x[keyPath: \.unavailableGetterAndSetter] = someValue
169+
x[keyPath: \.unavailableGetterAndSetter.a] = someValue.a // FIXME: missing diagnostics for getter and setter
170+
x[keyPath: \.unavailableGetterAndSetter[0]] = someValue.a // FIXME: missing diagnostics for getter and setter
171+
x[keyPath: \.unavailableGetterAndSetter[0].b] = 1 // FIXME: missing diagnostics for getter and setter
172+
a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter.a.b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter
173+
a[keyPath: \.[takesIntInOut(&x.unavailableGetterAndSetter[0].b)]] = 0 // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
174+
}
175+
176+
func testMutatingMember() {
177+
var x = BaseStruct()
178+
let a = [0]
179+
180+
x.available.setToZero()
181+
x.available[0].setToZero()
182+
_ = a[x.available.setToZero()]
183+
_ = a[x.available.a.setToZero()]
184+
_ = a[x.available[0].setToZero()]
185+
186+
x.unavailableGetter.setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}}
187+
x.unavailableGetter[0].setToZero() // expected-error {{getter for 'unavailableGetter' is unavailable}}
188+
_ = a[x.unavailableGetter.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
189+
_ = a[x.unavailableGetter.a.setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
190+
_ = a[x.unavailableGetter[0].setToZero()] // expected-error {{getter for 'unavailableGetter' is unavailable}}
191+
192+
x.unavailableSetter.setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}}
193+
x.unavailableSetter[0].setToZero() // expected-error {{setter for 'unavailableSetter' is unavailable}}
194+
_ = a[x.unavailableSetter.setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}}
195+
_ = a[x.unavailableSetter.a.setToZero()] // FIXME: missing diagnostic for setter
196+
_ = a[x.unavailableSetter[0].setToZero()] // expected-error {{setter for 'unavailableSetter' is unavailable}}
197+
198+
x.unavailableGetterAndSetter.setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
199+
x.unavailableGetterAndSetter[0].setToZero() // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
200+
_ = a[x.unavailableGetterAndSetter.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
201+
_ = a[x.unavailableGetterAndSetter.a.setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: should diagnose setter
202+
_ = a[x.unavailableGetterAndSetter[0].setToZero()] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
203+
}
204+
205+
func testPassAsInOutParameter() {
206+
func takesInOut<T>(_ t: inout T) {}
207+
208+
var x = BaseStruct()
209+
210+
takesInOut(&x.available)
211+
takesInOut(&x.available.a)
212+
takesInOut(&x.available[0])
213+
takesInOut(&x.available[0].b)
214+
215+
takesInOut(&x.unavailableGetter) // expected-error {{getter for 'unavailableGetter' is unavailable}}
216+
takesInOut(&x.unavailableGetter.a) // expected-error {{getter for 'unavailableGetter' is unavailable}}
217+
takesInOut(&x.unavailableGetter[0]) // expected-error {{getter for 'unavailableGetter' is unavailable}}
218+
takesInOut(&x.unavailableGetter[0].b) // expected-error {{getter for 'unavailableGetter' is unavailable}}
219+
220+
takesInOut(&x.unavailableSetter) // expected-error {{setter for 'unavailableSetter' is unavailable}}
221+
takesInOut(&x.unavailableSetter.a) //
222+
takesInOut(&x.unavailableSetter[0]) // expected-error {{setter for 'unavailableSetter' is unavailable}}
223+
takesInOut(&x.unavailableSetter[0].b) // expected-error {{setter for 'unavailableSetter' is unavailable}}
224+
225+
takesInOut(&x.unavailableGetterAndSetter) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
226+
takesInOut(&x.unavailableGetterAndSetter.a) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} FIXME: missing diagnostic for setter
227+
takesInOut(&x.unavailableGetterAndSetter[0]) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
228+
takesInOut(&x.unavailableGetterAndSetter[0].b) // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}}
229+
}
230+
231+
var global = BaseStruct()
232+
233+
struct TestPatternBindingInitExprs {
234+
var available = global.available
235+
var available_a = global.available.a
236+
var available_0 = global.available[0]
237+
var available_0_b = global.available[0].b
238+
239+
var unavailableGetter = global.unavailableGetter // expected-error {{getter for 'unavailableGetter' is unavailable}}
240+
var unavailableGetter_a = global.unavailableGetter.a // expected-error {{getter for 'unavailableGetter' is unavailable}}
241+
var unavailableGetter_0 = global.unavailableGetter[0] // expected-error {{getter for 'unavailableGetter' is unavailable}}
242+
var unavailableGetter_0_b = global.unavailableGetter[0].b // expected-error {{getter for 'unavailableGetter' is unavailable}}
243+
244+
var unavailableSetter = global.unavailableSetter
245+
var unavailableSetter_a = global.unavailableSetter.a
246+
var unavailableSetter_0 = global.unavailableSetter[0] // expected-error {{setter for 'unavailableSetter' is unavailable}} FIXME: setter should not be diagnosed
247+
var unavailableSetter_0_b = global.unavailableSetter[0].b // expected-error {{setter for 'unavailableSetter' is unavailable}}
248+
249+
var unavailableGetterAndSetter = global.unavailableGetterAndSetter // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
250+
var unavailableGetterAndSetter_a = global.unavailableGetterAndSetter.a // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}}
251+
var unavailableGetterAndSetter_0 = global.unavailableGetterAndSetter[0] // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} FIXME: setter should not be diagnosed
252+
var unavailableGetterAndSetter_0_b = global.unavailableGetterAndSetter[0].b // expected-error {{getter for 'unavailableGetterAndSetter' is unavailable}} expected-error {{setter for 'unavailableGetterAndSetter' is unavailable}} FIXME: setter should not be diagnosed
253+
}

0 commit comments

Comments
 (0)