I’m generally in favor of this and can already think of a few specific locations where this would improve performance in a meaningful way (when coupled with
take expressions), even without any further language changes. Also very excited about the general progress towards move-only types.
Inside of a function or closure body,
take parameters may be mutated, as can the
self parameter of a
taking func method.
I feel like this isn’t necessarily justified; while it is just as reasonable to mutate a
take parameter as a local
var, I don’t think it makes sense for that to be the default. With locals we still encourage
take doesn’t imply “mutation” to me. Certainly the implicit uses of the
take convention today aren’t about mutating the value; they’re about storing it. Similarly, the use case I have in mind is purely about allowing the parameter to be destroyed sooner, avoiding having to wait for a deep stack to return.
I suppose you can always convert from one form to another by
takeing into a local, but I don’t think
take should imply mutability like
inout do. I’d rather see a (separate) proposal to revert SE-0003 and revive
var on parameters if we think this is interesting, noting that SE-0031 moved
inout to the “type” side of the parameter declaration since SE-0003 was reviewed.
take cannot be applied to parameters of nonescaping closure type, which by their nature are always borrowed
The full form of a non-optional
take closure parameter would thus be
callback: take @escaping () -> Void, which is pretty verbose. (Or is it
@escaping take () -> Void?) Given that escaping pretty much implies that a copy will be made anyway, does it make sense for
take to imply
inout already does today? That still leaves the occasional
borrow @escaping () -> Void for where an escaping closure parameter might normally be
taken, but that seems pretty rare to me; the main place where I could see it being useful is if the closure is only escaped some of the time.
On the implementation side: are non-escaping closure parameters passed
take to initializers today? I would hope
borrow even though the usual convention for initializer parameters is
take, for the reasons discussed in this proposal, but if not this could be a good opportunity to fix some conventions (where not ABI-breaking).
Additionally, I remember the first implementation of
__shared affecting a function’s mangled name even if the convention matches the implicit default for that parameter. Does that behavior extend to
borrow, and if not…I guess there’ll be a special opt-out or shim for the stdlib, to use the explicit mangling where an implicit one would have done?
Again, very excited about all this! Thank you Michael, Joe, and everyone working on this.