[Returned for Revision] SE-0293: Extend Property Wrappers to Function and Closure Parameters

The review of SE-0293 Extend Property Wrappers to Function and Closure Parameters has concluded and the core team has returned it for revision.

Most of the discussion in the feedback thread centered around a central question of "what is the type of a function that has a property wrapper parameter?". The proposal describes a model where the wrapper is part of the exposed type (e.g. (Binding<Item>)->Void), but many data points in the thread argued for a model where the exposed type of a function is the unwrapped type (e.g. (Item)->Void). These data points include:

  1. This aligns direct calls and indirect calls with the same model.
  2. This doesn't allow reuse/aliasing of wrappers at the call site.
  3. This maintains a simplicity in the function overloading model, because property wrappers are ignored.

Beyond the points in the thread, the core team discussion raised several other questions:

  1. The resilience impact of this proposal wasn't discussed - should addition and removal of property wrappers to a resilient function affect its ABI and source compatibility?

  2. Many property wrappers are aspects of the implementation not its interface, e.g. adding a Rounded property wrapper shouldn't impact ABI or exposed user behavior.

  3. If we ever support parameter attributes with arguments (e.g. the @Clamped(2...3) example from the thread) then we need to decide whether the expression is evaluated on the caller or callee side.

  4. We need to decide how these would work in generated interfaces.

  5. The functionality that allows "unwrapping" property wrappers in the pattern of a closure argument (e.g. { (@Binding item) in) could alternatively be imagined as an orthogonal feature that applies to all patterns. If it were, such an unwrapping could work consistently in other places where patterns exist, for example for @Binding item in items, in switch case patterns, if case, etc. It would be interesting to explore such a direction.

The fundamental question is really "is the parameter wrapper an artifact of a function's implementation or a part of its interface?". In the core team discussion, several members felt like it would be a much simpler and more consistent model to make them an artifact of the implementation and not be exposed through type, ABI or in any other way. This would allow a function implementation to resiliently add new parameter attributes (e.g. to document preconditions), and maintains a simple model.

The core team acknowledges that there could be a use case for exposing explicit wrapper manipulation to the caller (e.g. with syntax like foo($a: explicitWrapper)). However, if this were important to support, this should be an opt-in feature rather than opt-out, in accordance with our general design that avoids unnecessary ABI commitments for implementation details.

Overall, the proposal is well written and there is strong positive feedback from the community about the idea and direction proposed. I would like to thank the authors of the proposal, thank the community for your participation, and encourage a revision and resubmission of the proposal!

Chris Lattner
Release Manager

22 Likes

Could you elaborate more on what do you mean by "reusing/aliasing"?

Emphasis added. :thinking: Never think of the closure arguments that way. (deep voice This changes everything.)

1 Like

I mean the @Box example brought up in the review thread.

Yeah, closure arguments should work the same ways as "destructuring" patterns, used in let and for (key,value) in... for example.

-Chris

1 Like

That's one potential design that can be discussed when the proposal comes up again. It's not the only design.

Doug

4 Likes