@@ -124,7 +124,111 @@ already infer from static analysis.
124124Changing the implementation in a way that violates the optimizer's assumptions
125125about the effects results in undefined behavior.
126126
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.
128232
129233## ` @_exported `
130234
0 commit comments