@@ -124,7 +124,111 @@ already infer from static analysis.
124
124
Changing the implementation in a way that violates the optimizer's assumptions
125
125
about the effects results in undefined behavior.
126
126
127
- For more details, see [ OptimizerEffects.rst] ( /docs/proposals/OptimizerEffects.rst ) .
127
+ ### ` @_effects(readnone) `
128
+
129
+ Defines that the function does not have any observable memory reads or writes
130
+ or any other observable side effects.
131
+
132
+ This does not mean that the function cannot read or write memory at all.
133
+ For example, it’s allowed to allocate and write to local objects inside the
134
+ function. For example, the following ` readnone ` function allocates an array and
135
+ writes to the array buffer
136
+
137
+ ``` swift
138
+ @_effects (readnone)
139
+ func lookup (_ i : Int ) -> Int {
140
+ let a = [7 , 3 ,6 , 9 ]
141
+ return a[i]
142
+ }
143
+ ```
144
+
145
+ A function can be marked as readnone if two calls of the same function with the
146
+ same parameters can be simplified to one call (e.g. by the CSE optimization)
147
+ without changing the semantics of the program.
148
+ For example,
149
+
150
+ ``` swift
151
+ let a = lookup (i)
152
+ // some other code, including memory writes
153
+ let b = lookup (i)
154
+ ```
155
+ is equivalent to
156
+
157
+ ``` swift
158
+ let a = lookup (i)
159
+ // some other code, including memory writes
160
+ let b = a
161
+ ```
162
+
163
+ Some conclusions:
164
+
165
+ * A ` readnone ` function must not return a newly allocated class instance.
166
+
167
+ * A ` readnone ` function can return a newly allocated copy-on-write object, like
168
+ an Array, because COW data types conceptually behave like value types.
169
+
170
+ * A ` readnone ` function must not release any parameter or any object indirectly
171
+ referenced from a parameter.
172
+
173
+ * Any kind of observable side-effects are not allowed, like ` print ` , file IO, etc.
174
+
175
+ ### ` @_effects(readonly) `
176
+
177
+ Defines that the function does not have any observable memory writes or any
178
+ other observable side effects, beside reading of memory.
179
+
180
+ Similar to ` readnone ` , a ` readonly ` function is allowed to write to local objects.
181
+
182
+ A function can be marked as ` readonly ` if it’s save to eliminate a call to such
183
+ a function in case its return value is not used.
184
+ Example:
185
+
186
+ ``` swift
187
+ @_effects (readonly)
188
+ func lookup2 (_ instance : SomeClass) -> Int {
189
+ let a = [7 , 3 ,6 , 9 ]
190
+ return a[instance.i ]
191
+ }
192
+ ```
193
+
194
+ It is legal to eliminate an unused call to this function:
195
+
196
+ ```
197
+ _ = lookup2(i) // can be completely eliminated
198
+ ```
199
+
200
+ Note that it would not be legal to CSE two calls to this function, because
201
+ between those calls the member ` i ` of the class instance could be modified:
202
+
203
+ ``` swift
204
+ let a = lookup2 (instance)
205
+ instance.i += 1
206
+ let b = lookup2 (instance) // cannot be CSE'd with the first call
207
+ ```
208
+
209
+ The same conclusions as for ` readnone ` also apply to ` readonly ` .
210
+
211
+ ### ` @_effects(releasenone) `
212
+
213
+ Defines that the function does not release any class instance.
214
+
215
+ This effect must be used with care.
216
+ There are several code patterns which release objects in a non-obvious way.
217
+ For example:
218
+
219
+ * A parameter which is passed to an “owned” argument (and not stored), like
220
+ initializer arguments.
221
+
222
+ * Assignments, because they release the old value
223
+
224
+ * COW data types, e.g. Strings. Conceptually they are value types, but
225
+ internally the keep a reference counted buffer.
226
+
227
+ * Class references deep inside a hierarchy of value types.
228
+
229
+ ### ` @_effects(readwrite) `
230
+
231
+ This effect is not used by the compiler.
128
232
129
233
## ` @_exported `
130
234
0 commit comments