Skip to content

Commit e76c534

Browse files
committed
Document _effects(readonly) pitfalls
And the new _effects(releasenone) requirement.
1 parent fc640db commit e76c534

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,18 @@ Some conclusions:
218218

219219
* Any kind of observable side-effects are not allowed, like `print`, file IO, etc.
220220

221+
The `readnone` attribute cannot be used on functions that take
222+
nontrivial owned arguments for the reasons explained in the next
223+
section on `@_effects(readonly)`.
224+
221225
### `@_effects(readonly)`
222226

223227
Defines that the function does not have any observable memory writes or any
224228
other observable side effects, beside reading of memory.
225229

226230
Similar to `readnone`, a `readonly` function is allowed to write to local objects.
227231

228-
A function can be marked as `readonly` if it’s save to eliminate a call to such
232+
A function can be marked as `readonly` if it’s safe to eliminate a call to such
229233
a function in case its return value is not used.
230234
Example:
231235

@@ -254,6 +258,44 @@ between those calls the member `i` of the class instance could be modified:
254258

255259
The same conclusions as for `readnone` also apply to `readonly`.
256260

261+
The `readonly` and `readnone` effects are sensitive to the ARC calling
262+
convention, which normally has no effect on language semantics. These
263+
effects attributes can only be used correctly by knowing whether the
264+
compiler will pass any nontrivial arguments as guaranteed or owned. If
265+
the function takes an owned argument, as is the case for initializers
266+
and setters, then `readonly` is likely invalid because removing the call
267+
would fail to release the argument. Additionally, the release itself
268+
may run a tree of deinitializers with potentially arbitrary side
269+
effects.
270+
271+
In special situations, the library author may still want to use
272+
`readonly` for functions with owned arguments. They must be able to
273+
guarantee that the owned arguments are not effectively released from
274+
the caller's perspective. This could be because all paths through the
275+
function have an equivalent retain, or they may know that the argument
276+
is a tagged object for which a release has no effect. To make sure
277+
this is intentional, the library author must also explicitly specify
278+
`_effects(releasenone)` even though that is normally already implied
279+
by `readonly`.
280+
281+
For example, it is valid to give the following trivial initializer
282+
`readonly` and `releasenone` attributes:
283+
284+
@_effects(readonly) @_effects(releasenone)
285+
init(_ c: C) { self.c = c }
286+
287+
If `C` is a class, then the value returned by the initializer must
288+
have at least one use in the form of a release. The optimizer,
289+
therefore, may not remove the call to the initializer without
290+
deliberately compensating for ownership.
291+
292+
For the same reason that developers must take care regarding argument
293+
ownership, the compiler must always check for `readonly` and
294+
`readnone` effects attributes before transforming a function
295+
signature. Normally, this optimization can be done independent of
296+
language semantics, but such optimizations should be avoided for
297+
functions with these effects attributes.
298+
257299
### `@_effects(releasenone)`
258300

259301
Defines that the function does not release any class instance.

0 commit comments

Comments
 (0)