Skip to content

Commit a4dbe67

Browse files
authored
Merge pull request #29440 from gottesmm/pr-1b807b886ce5cba8ed0e399f6a2e27efd5b4049e
[sil.rst] Clarify documentation around partial_apply closure contexts/closed over parameters.
2 parents f0173b3 + c97a0cf commit a4dbe67

File tree

1 file changed

+50
-40
lines changed

1 file changed

+50
-40
lines changed

docs/SIL.rst

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,46 +3495,8 @@ partial_apply
34953495
// %r will be of the substituted thick function type $(Z'...) -> R'
34963496

34973497
Creates a closure by partially applying the function ``%0`` to a partial
3498-
sequence of its arguments. In the instruction syntax, the type of the callee is
3499-
specified after the argument list; the types of the argument and of the defined
3500-
value are derived from the function type of the callee. If the ``partial_apply``
3501-
has an escaping function type (not ``[on_stack]``) the closure context will be
3502-
allocated with retain count 1 and initialized to contain the values ``%1``,
3503-
``%2``, etc. The closed-over values will not be retained; that must be done
3504-
separately before the ``partial_apply``. The closure does however take ownership
3505-
of the partially applied arguments (except for ``@inout_aliasable`` parameters);
3506-
when the closure reference count reaches zero, the contained values will be
3507-
destroyed. If the ``partial_apply`` has a ``@noescape`` function type
3508-
(``partial_apply [on_stack]``) the closure context is allocated on the stack and
3509-
initialized to contain the closed-over values. The closed-over values are not
3510-
retained, lifetime of the closed-over values must be managed separately. The
3511-
lifetime of the stack context of a ``partial_apply [on_stack]`` must be
3512-
terminated with a ``dealloc_stack``.
3513-
3514-
If the callee is generic, all of its generic parameters must be bound by the
3515-
given substitution list. The arguments are given with these generic
3516-
substitutions applied, and the resulting closure is of concrete function
3517-
type with the given substitutions applied. The generic parameters themselves
3518-
cannot be partially applied; all of them must be bound. The result is always
3519-
a concrete function.
3520-
3521-
If an address argument has ``@inout_aliasable`` convention, the closure
3522-
obtained from ``partial_apply`` will not own its underlying value.
3523-
The ``@inout_aliasable`` parameter convention is used when a ``@noescape``
3524-
closure captures an ``inout`` argument.
3525-
3526-
TODO: The instruction, when applied to a generic function,
3527-
currently implicitly performs abstraction difference transformations enabled
3528-
by the given substitutions, such as promoting address-only arguments and returns
3529-
to register arguments. This should be fixed.
3530-
3531-
By default, ``partial_apply`` creates a closure whose invocation takes ownership
3532-
of the context, meaning that a call implicitly releases the closure. The
3533-
``[callee_guaranteed]`` change this to a caller-guaranteed model, where the
3534-
caller promises not to release the closure while the function is being called.
3535-
3536-
This instruction is used to implement both curry thunks and closures. A
3537-
curried function in Swift::
3498+
sequence of its arguments. This instruction is used to implement both curry
3499+
thunks and closures. A curried function in Swift::
35383500

35393501
func foo(_ a:A)(b:B)(c:C)(d:D) -> E { /* body of foo */ }
35403502

@@ -3607,6 +3569,54 @@ lowers to an uncurried entry point and is curried in the enclosing function::
36073569
return %ret : $Int
36083570
}
36093571

3572+
**Ownership Semantics of Closure Context during Invocation**: By default, an
3573+
escaping ``partial_apply`` (``partial_apply`` without ``[on_stack]]`` creates a
3574+
closure whose invocation takes ownership of the context, meaning that a call
3575+
implicitly releases the closure. If the ``partial_apply`` is marked with the
3576+
flag ``[callee_guaranteed]`` the invocation instead uses a caller-guaranteed
3577+
model, where the caller promises not to release the closure while the function
3578+
is being called.
3579+
3580+
**Captured Value Ownership Semantics**: In the instruction syntax, the type of
3581+
the callee is specified after the argument list; the types of the argument and
3582+
of the defined value are derived from the function type of the callee. Even so,
3583+
the ownership requirements of the partial apply are not the same as that of the
3584+
callee function (and thus said signature). Instead:
3585+
3586+
1. If the ``partial_apply`` has a ``@noescape`` function type (``partial_apply
3587+
[on_stack]``) the closure context is allocated on the stack and is
3588+
initialized to contain the closed-over values without taking ownership of
3589+
those values. The closed-over values are not retained and the lifetime of the
3590+
closed-over values must be managed by other instruction independently of the
3591+
``partial_apply``. The lifetime of the stack context of a ``partial_apply
3592+
[on_stack]`` must be terminated with a ``dealloc_stack``.
3593+
3594+
2. If the ``partial_apply`` has an escaping function type (not ``[on_stack]``)
3595+
then the closure context will be heap allocated with a retain count of 1. Any
3596+
closed over parameters (except for ``@inout`` parameters) will be consumed by
3597+
the partial_apply. This ensures that no matter when the ``partial_apply`` is
3598+
called, the captured arguments are alive. When the closure context's
3599+
reference count reaches zero, the contained values are destroyed. If the
3600+
callee requires an owned parameter, then the implicit partial_apply forwarder
3601+
created by IRGen will copy the underlying argument and pass it to the callee.
3602+
3603+
3. If an address argument has ``@inout_aliasable`` convention, the closure
3604+
obtained from ``partial_apply`` will not own its underlying value. The
3605+
``@inout_aliasable`` parameter convention is used when a ``@noescape``
3606+
closure captures an ``inout`` argument.
3607+
3608+
**NOTE:** If the callee is generic, all of its generic parameters must be bound
3609+
by the given substitution list. The arguments are given with these generic
3610+
substitutions applied, and the resulting closure is of concrete function type
3611+
with the given substitutions applied. The generic parameters themselves cannot
3612+
be partially applied; all of them must be bound. The result is always a concrete
3613+
function.
3614+
3615+
**TODO:** The instruction, when applied to a generic function, currently
3616+
implicitly performs abstraction difference transformations enabled by the given
3617+
substitutions, such as promoting address-only arguments and returns to register
3618+
arguments. This should be fixed.
3619+
36103620
builtin
36113621
```````
36123622
::

0 commit comments

Comments
 (0)