[Pitch #4] SE-0293: Extend Property Wrappers to Function and Closure Parameters

I want to make a few observations regarding the relationship between API and Impl wrappers:

  • The main difference between the two is how they react when wrapping arguments. Wrappers that are not to be passed around, e.g., @State and most of what I called entity-bounded wrappers, could live their whole lives not knowing (nor caring) what exactly they are.
  • An Impl wrapper can evolve into an API wrapper. It can gain more functionality over time, to the point where interfacing with the wrapper becomes significant. For example, Atomic could be Impl wrapper that passes in initial value. It could then become API wrapper that accepts an already-atomic values.
  • Wrong decision for whether a wrapper is API or Impl is impactful, changing between them is a breaking change. There is no "default" choice that a "don't care" wrapper can choose. The wrapper author needs to choose them (wisely) early on.
  • Every API wrapper can become an Impl wrapper using local variable wrappers. It's the Impl wrappers that can't become API wrappers, not without a more sophisticated workaround, like creating a new wrapper type.

These observations hint toward my conclusion that the relationship between API and Impl wrappers isn't that of a dichotomy but a subdivision. Every wrapper is an Impl wrapper, some of which are also API wrappers. I think we should treat API wrappers as a special case of Impl wrappers, not a distinct part from it.

If we look through subdivision lens, we can see why there is a lot of friction unifying this feature. Two distinct features are hiding underneath (as many already probably grok). Now, there's nothing wrong with adding multiple features at once. We could argue that SE-0269 has two components. The problem with this one is that the two are intruding on the same syntactical space, trying to impose different interpretations. The Impl part is sugar for every local variable wrapper, while the API part introduces a notion of caller cooperation through it–they are incongruent. It is evident from the fact that we need to change the type checking rule just to make them look remotely similar. Even then, the two features desugar to entirely different codes, have different interpretations, and even result in different ABIs.

While I don't think it's impossible to marry two entirely different features, it wouldn't be without sizable compromises.


What if we allow argument wrapper only for the API wrappers, marked by @propertyWrapper(api), or @propertyWrapper(visible), or use heuristic as suggested above. Then we raise an error when someone tried to wrap arguments with non-API wrappers while offering a fix-it.