# \[Pitch #5\] SE-0293: Extend property wrappers to function and closure parameters

**URL:** <https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040>\
**Category:** Pitches\
**Tags:** propertywrapper\
**Created:** [February 23, 2021, 9:06pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040 "2021-02-23T21:06:24Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 23, 2021, 9:06pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/1 "2021-02-23T21:06:24Z")

</div>

Hello, Swift Community

@filip-sakel have revised the design of SE-0293 again based on feedback from the [last pitch discussion](https://forums.swift.org/t/pitch-4-se-0293-extend-property-wrappers-to-function-and-closure-parameters/44858). The latest proposal draft is available [here](https://github.com/hborla/swift-evolution/blob/se-0293-revision-3/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md).

Here is a list of changes to the design in this revision (compared to the last reviewed version):

- The distinction between API wrappers and implementation-detail wrappers is formalized, and determined by the compiler based on whether the property wrapper type allows the call-site to pass a different type of argument.
- Implementation-detail property wrappers on parameters are sugar for a local wrapped variable.
- API property wrappers on parameters use caller-side application of the property wrapper.
- Overload resolution for property wrapper initializers will always be done at the property wrapper declaration to minimize the semantic differences between the two property wrapper models.

For those who have been actively following the discussion, here are a few new sections that might be of interest:

- [Inference of API-level property wrappers](https://github.com/hborla/swift-evolution/blob/se-0293-revision-3/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md#inference-of-api-level-property-wrappers)
- (Alternatives Considered) [Only allow implementation-detail property wrappers on function parameters](https://github.com/hborla/swift-evolution/blob/se-0293-revision-3/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md#only-allow-implementation-detail-property-wrappers-on-function-parameters)

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [February 23, 2021, 10:30pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/2 "2021-02-23T22:30:29Z")

</div>

Thanks for your continued work on this, @hborla and @filip-sakel! I like how this iteration turned out and appreciate all the hard work that went into it.

I do wonder if you could elaborate on this point a bit:

> These two models are designed such that nearly all observable semantics of property wrapper application do not differ based on where the wrapper is applied. The only observable semantic difference that the proposal authors can think of is evaluation order among property wrapper initialization and other arguments that are passed to the API, and the proposal authors believe it is extremely unlikely that this evaluation order will have any impact on the functionality of the code. For evaluation order to have a functional impact, both the property wrapper initializer _and_ another function argument would both need to call into a separate function that has some side effect.

Could you give an example (a toy example would be fine) of what you're describing? It does sound like a bit of an elaborate situation, but it'd be good to visualize it in code.

* * *

Going back to the method by which the compiler determines whether a property wrapper type has API significance--I think this is very much acceptable _given the point above about consistency of observable semantics_ for property wrapper application. That provides a nice justification for why the two "different" types of wrappers don't need to look "different" when decorating function parameters. It would be nice if the proposal explicitly regarded this consistency of observable semantics as a fundamental design goal, and therefore any divergences as bugs.

I think the classification of any property wrapper that supports projected-value initialization as having API significance is very sensible and easily justifiable to users: that there is such a projected value initializer is a pretty big declaration of intent, in my view.

I'm not so sure I understand the second point about `@autoclosure` arguments to `init(wrappedValue:)`. That is, I get why they _can't_ be implementation-detail wrappers, but why not just reject them altogether for use in parameter lists given that they don't meet the requirement that's been stated: "implementation-detail property wrappers on parameters _must support initialization via wrapped value_"? In other words, is there a use case for property wrappers that take `@autoclosure` wrapped values being supported as API-significant wrappers?

It would seem to simplify things greatly in terms of learnability to say you can use a wrapper for a function parameter if the wrapper (1) supports initialization via same-type wrapped value as an implementation detail; or (2) supports initialization via a projected value as an API-level matter.

[Edit: We could even, then, formalize the distinction between these two kinds of property wrappers along those lines: we'd have _value-projecting_ property wrappers and (ugh, I've run out of a good term here) _non-value-projecting_ property wrappers.]

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 24, 2021, 1:01am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/3 "2021-02-24T01:01:37Z")

</div>

> [@xwu](#):
>
> Could you give an example (a toy example would be fine) of what you're describing? It does sound like a bit of an elaborate situation, but it'd be good to visualize it in code.

I added an example to the proposal. It looks like this:

```swift
func hasSideEffect() -> Int {
  struct S {
    static var state = 0
  }

  S.state += 1
  return S.state
}

@propertyWrapper
struct Wrapper {
  var wrappedValue: Int

  init(wrappedValue: Int) {
    self.wrappedValue = wrappedValue + hasSideEffect()
  }
}

func demonstrateEvaluationOrder(@Wrapper arg1: Int, arg2: Int) {
  print(arg1, arg2)
}

demonstrateEvaluationOrder(arg1: 1, arg2: hasSideEffect())

```

If the property wrapper initializer is evaluated in the caller, the output of this code is `2, 2`. If the property wrapper initializer is evaluated in the callee, the output of the code is `3, 1`.

> [@xwu](#):
>
> I'm not so sure I understand the second point about `@autoclosure` arguments to `init(wrappedValue:)` . That is, I get why they _can't_ be implementation-detail wrappers, but why not just reject them altogether for use in parameter lists given that they don't meet the requirement that's been stated: "implementation-detail property wrappers on parameters _must support initialization via wrapped value_ "? In other words, is there a use case for property wrappers that take `@autoclosure` wrapped values being supported as API-significant wrappers?

Part of the reason for including `@autoclosure` is because `@autoclosure` is already propagated from `init(wrappedValue:)` to the type of a parameter today via the memberwise initializer. I think memberwise initialization is a reasonable use case for this behavior. I could also imagine a property wrapper that lazily evaluates arguments.

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [February 24, 2021, 1:02am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/4 "2021-02-24T01:02:30Z")

</div>

> [@xwu](#):
>
> Going back to the method by which the compiler determines whether a property wrapper type has API significance--I think this is very much acceptable _given the point above about consistency of observable semantics_ for property wrapper application. That provides a nice justification for why the two "different" types of wrappers don't need to look "different" when decorating function parameters. It would be nice if the proposal explicitly regarded this consistency of observable semantics as a fundamental design goal, and therefore any divergences as bugs.

The current restriction is a good starting point, but not an ideal end version of this feature –– as I see it. This proposal, as pointed out in the 4th pitch discussion, was too complex and instructions for authors to properly determine the API significance for their wrappers wasn’t discussed thoroughly. This would likely lead to this feature being widely misused. A well-crafted proposal, though, focused solely on enabling explicit marking of API significance while also guiding authors to correct usage would greatly benefit libraries –– and users to a lesser extent.

I'll update the future direction of explicitly marking API significance to elaborate on this.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 24, 2021, 1:59am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/5 "2021-02-24T01:59:36Z")

</div>

I think what @xwu pointed out _is_ a design goal. Users shouldn't have to think about where exactly the wrapper is initialized to figure out what their code is doing. Sure, it might be nice for `#file`, `#line`, etc. to work in the future -- and that's possible -- but beyond that, I don't think semantic differences are desirable. The simpler the mental model for the programmer, the better.

There are a lot of interesting future directions for this feature, but as long as the current design isn't cutting off any of those directions, I think it's important to try to focus the discussion here on what's being proposed now (and more specifically, the updates in this revision).

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 24, 2021, 6:52am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/6 "2021-02-24T06:52:15Z")

</div>

The proposal is a bit tricky. What is the reason to restrict mutability for `mutating` setters in case of implementation detail property wrappers? I feel like the proposal tries to keep consistency between api and impl. detail PWs but that‘s the tricky part here.

I could write the desugared line of code by hand and create a local PW which would result in a mutable variable. So why isn‘t it the same for impl. detail PWs already?

```swift
func insert(@Logged text: String) { ... }

// The above code is sugar for:

func insert(text: String) {
  @Logged var text = text
}

// which the compiler further desugars to generate:

func insert(text: String) {
  var _text: Logged<String> = Logged(wrappedValue: text)

  var text: String { 
    get { _text.wrappedValue }
    // missing part
    set { _text.wrappedValue = newValue }
  }
}

```

That said, if we already using local property wrappers, then I don‘t see the point for api property wrappers having the same restriction.

Instead of this:

```swift
func copy(_text: Traceable<String>) {
  var text: String {
    get { _text.wrappedValue }
  }

  var $text: History<String> {
    get { _text.projectedValue }
  }

  ...
}

```

We could generalize the above idea and go a step further:

```swift
func copy(_text: Traceable<String>) {

  var _text: Traceable<String> = _text
  var text: String {
    get { _text.wrappedValue }
    // synthesize a setter if PW has a setter on wrappedValue
  }

  var $text: History<String> {
    get { _text.projectedValue }
   // synthesize a setter if PW has a setter on projectedValue
  }

  ...
}

```

This is simple to remember, teachable, less restricting and consistent across across both api and impl. detail wrappers.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 24, 2021, 8:38am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/7 "2021-02-24T08:38:14Z")

</div>

I will try to provide a more extensive review of the current proposal today or tomorrow. I have to sort my thoughts first. 🙂 The proposal made a long way up until now and is great but I think we can improve and fine tune it even more to have a greater flexibility for everyone.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 24, 2021, 4:51pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/8 "2021-02-24T16:51:18Z")

</div>

> [@DevAndArtist](#):
>
> What is the reason to restrict mutability for `mutating` setters in case of implementation detail property wrappers?

Because conceptually, parameters are immutable, and it can be surprising when it appears that you're able to set a parameter without the change being reflected in the argument that was passed when the caller resumes.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 24, 2021, 5:37pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/9 "2021-02-24T17:37:15Z")

</div>

It is true for normal parameters, but we're no longer talking about normal parameters. If we extend the synthesized code for api property wrappers, we would align the rules and simplify the design of the synthetic code. If we say that a wrapper on a parameter always desugars to a local property wrapper which shadows the parameter, there is clearly an opportunity to allow mutation.

In fact, you (the proposal authors) already propose to synthesise setters if the PW's `wrappedValue / projectedValue` has a `nonmutating` setter. Sure this indicates that there will be an effect that the user can trigger. However for super simple PWs there will be no effect except that you will mutate the value in the backing storage.

As mentioned by someone in the previous thread, this isn't a basic feature anymore and I don't see the requirement to artificially restrict it. Api or implementation detail property wrapper, both should just produce a local property wrapper variable. That is far more flexible. If you recall in the early stages of the original PW proposal we had PWs that were forced to have a generic type parameter that represented the type of `wrappedValue`. That restriction was totally unnecessary and would have caused more issues than the design we have today.

Here is a quick but simple example:

```swift
@propertyWrapper
struct Clamping<Value> where Value: Comparable {
  var value: Value
  let range: ClosedRange<Value>

  init(wrappedValue: Value, range: ClosedRange<Value>) {
    precondition(range.contains(wrappedValue))
    self.value = wrappedValue
    self.range = range
  }

  var wrappedValue: Value {
    get {
      return value
    }
    set {
      if newValue < range.lowerBound {
        value = range.lowerBound
      } else if newValue > range.upperBound {
        value = range.upperBound
      } else {
        value = newValue
      }
    }
  }
}

@propertyWrapper
struct W {
  @Clamping
  var wrappedValue: Double

  var projectedValue: Int {
    get { Int(wrappedValue) }
    set { wrappedValue = Double(newValue) }
  }

  init(wrappedValue: Double) {
    self._wrappedValue = Clamping(wrappedValue: wrappedValue , range: 0 ... 10)
  }

  init(projectedValue: Int) {
    self.init(wrappedValue: Double(projectedValue))
  }
}

// func foo(@W value: Double)
func foo(value _value: W) {
  // the key alignment between api and implementation detail PWs.
  var _value: W = _value

  // syntheized computed property
  var value: Double {
    get { _value.wrappedValue }
    set { _value.wrappedValue = newValue }
  }

  // syntheized computed property
  var $value: Int {
    get { _value.projectedValue }
    set { _value.projectedValue = newValue }
  }

  print(value, $value)

  value = 5.5

  print(value, $value)

  $value = 4

  print(value, $value)
}

foo(value: 20.5)
// foo(value: W(wrappedValue: 20.5))

// prints:
// 10.0 10
// 5.5 5
// 4.0 4

foo($value: 2)
// foo(value: W(projectedValue: 2))

// prints:
// 2.0 2
// 5.5 5
// 4.0 4

```

There is no reason to artificially restrict code that is "just sugar" for the most part.

* * *

As for the implementation detail PW from the proposal:

> ```swift
> func insert(@Logged text: String) { ... }
> 
> ```
> 
> The above code is sugar for:
> 
> ```swift
> func insert(text: String) {
> @Logged var text = text
> }
> 
> ```
> 
> which the compiler further desugars to generate:
> 
> ```swift
> func insert(text: String) {
> var _text: Logged<String> = Logged(wrappedValue: text)
> 
> var text: String { _text.wrappedValue }
> }
> 
> ```

That is incorrect. In Swift 5.4 the following code

```swift
func insert(text: String) {
  @Logged var text = text
}

```

would already desugar to this:

```swift
func insert(text: String) {
  var _text: Logged<String> = Logged(wrappedValue: text)

  var text: String { 
    get { _text.wrappedValue }
    set { _text.wrappedValue = newValue }
  }
}

```

* * *

As I wrote this example I realized that one example in the proposal seems to be incomplete.

```swift
// The compiler will synthesize computed text and $text variables in the body of copy(text:):
func copy(_text: Traceable<String>) {

// shouldn't this be?
func copy(text _text: Traceable<String>) {

```

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 24, 2021, 6:02pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/10 "2021-02-24T18:02:10Z")

</div>

> [@DevAndArtist](#):
>
> If we say that a wrapper on a parameter always desugars to a local property wrapper which shadows the parameter, there is clearly an opportunity to allow mutation.

Yes, it's feasible, but again, I believe it's unexpected when it appears that you're able to modify a parameter and that change isn't reflected when the caller resumes. This was also a point brought up in the first pitch of this feature:

> [@Pitch #2: Extend Property Wrappers to Function and Closure Parameters](https://forums.swift.org/t/pitch-2-extend-property-wrappers-to-function-and-closure-parameters/40959/2):
>
> Ever since [SE-0003](https://github.com/apple/swift-evolution/blob/main/proposals/0003-remove-var-parameters.md), parameters have been immutable. I feel like we shouldn’t let property wrappers change that, even when the wrappedValue is nonmutating.

The only reason we chose to synthesize nonmutating setters is that this is typically what's used for property wrappers that provide an abstracted reference to a value, and the ergonomics of using such property wrappers as parameters would be poor otherwise.

> [@DevAndArtist](#):
>
> That is incorrect. In Swift 5.4 the following code

I understand how local property wrappers work. What's in the proposal is deliberately different. I can make it more clear in the proposal that it's deliberately different.

> [@DevAndArtist](#):
>
> As I wrote this example I realized that one example in the proposal seems to be incomplete.

You're right - thanks for pointing this out, it was an inadvertent change I made as I updated the proposal for this revision. It's fixed now.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 24, 2021, 6:15pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/11 "2021-02-24T18:15:28Z")

</div>

> [@hborla](#):
>
> I understand how local property wrappers work. What's in the proposal is deliberately different. I can make it more clear in the proposal that it's deliberately different.

I do not doubt your understanding of the feature 😉 but the proposal claims that the transformation is achieved in two steps, or at least one gets the impression if you say that the implementation detail PW will compose a local property wrapper first before the final desugaring. In that sense it's not correct because the final transformation still should have the setter.

> [@Pitch #2: Extend Property Wrappers to Function and Closure Parameters](https://forums.swift.org/t/pitch-2-extend-property-wrappers-to-function-and-closure-parameters/40959/2):
>
> > [@Pitch #2: Extend Property Wrappers to Function and Closure Parameters](https://forums.swift.org/t/pitch-2-extend-property-wrappers-to-function-and-closure-parameters/40959/2):
> >
> > Ever since [SE-0003](https://github.com/apple/swift-evolution/blob/main/proposals/0003-remove-var-parameters.md), parameters have been immutable. I feel like we shouldn’t let property wrappers change that, even when the wrappedValue is nonmutating.
> 
> The only reason we chose to synthesize nonmutating setters is that this is typically what's used for property wrappers that provide an abstracted reference to a value, and the ergonomics of using such property wrappers as parameters would be poor otherwise.

I get the point, but I personally do not buy the argument for synthesized code that is only sugar for the user (not speaking about the parameter handling from the compiler, which is one of the major motivations for this proposal in the first place). We're not really outruling the immutability of parameters, we would just copy them into a backing storage which happens to be function local instead being an immutable parameter.

Let me use the implementation PW example from the proposal again.

If this

```swift
func insert(@Logged text: String) { ... }

```

transforms to

```swift
func insert(text: String) {
  @Logged var text = text
}

```

and finally to

```swift
func insert(text: String) {
  var _text: Logged<String> = Logged(wrappedValue: text)

  var text: String { _text.wrappedValue }
}

```

Then the result is artificially restricted and goes against the expected result for local property wrappers in Swift 5.4.

Not only that, if this restriction persists, why should I as a user use the property in such manner? Instead I would do the local property wrapper by hand and get the expected result.

```swift
func insert(text: String) {
  @Logged var text = text
}

```

That said, implementation detail property wrappers on parameters start to lose the motivation for their existence. The only benefit is that I don't have to do the shadowing by hand, but then it ends up in removing the setter for me. That is simply not what I would expect from this feature.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 24, 2021, 6:24pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/12 "2021-02-24T18:24:59Z")

</div>

I only had time to argue on that small adjustment. In fact, I think if we did it that way we can remove a few more restriction from the current proposal. There are a few other restrictions that I think we can provide a solution to, but I need a bit more time to parse the entire proposal and sort my arguments and ideas. 🙂

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [February 25, 2021, 12:38am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/13 "2021-02-25T00:38:28Z")

</div>

I'm pretty happy with this revision and don't have a lot to say (shocker!). IMO many of the minutiae at this point (such as the mutability decisions) are debatable but will ultimately come down to minor tradeoffs between different priorities, and I could really be happy with a principled stand in any direction.

I'll sit with this to see if anything comes to mind over the next few days, but this feels like a well-balanced proposal for a very complex feature. Kudos to the authors for their thoughtful engagement through several revisions!

---

<div class="post-metadata">

**Author:** ![xAlien95](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xalien95/32/12558_2.png) [@xAlien95](https://forums.swift.org/u/xAlien95)\
**Post date:** [February 25, 2021, 2:21am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/14 "2021-02-25T02:21:37Z")

</div>

I'm having some difficulties understanding the [Overload resolution of backing property wrapper initializer](https://github.com/hborla/swift-evolution/blob/se-0293-revision-3/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md#overload-resolution-of-backing-property-wrapper-initializer) subsection. Until the third pitch, overload resolution affected which `init(wrappedValue:)` was going to be used. Now it doesn't anymore, is that correct?

These quotes seem in contradiction to me:

> [@](#):
>
> Though the property wrapper is initialized at the call-site, the argument type _ **cannot** _ impact overload resolution of `init(wrappedValue:)` and `init(projectedValue:)`.

> [@](#):
>
> Overload resolution will choose which `init(wrappedValue:)` to call based on the static type of the parameter at the declaration of the property wrapper attribute [...]

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 25, 2021, 2:27am UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/15 "2021-02-25T02:27:44Z")

</div>

> [@xAlien95](#):
>
> These quotes seem in contradiction to me:
> 
> > [@](#):
> >
> > Though the property wrapper is initialized at the call-site, the argument type _ **cannot** _ impact overload resolution of `init(wrappedValue:)` and `init(projectedValue:)` .
> 
> > [@](#):
> >
> > Overload resolution will choose which `init(wrappedValue:)` to call based on the static type of the parameter at the declaration of the property wrapper attribute [...]

There is a difference between the parameter type and the argument type. For example:

```swift
func generic<T>(value: T) {}

generic(value: 10)

```

The type of the parameter is generic type `T`, and the type of the argument is `Int`. In this revision, the type of the parameter will impact `init(wrappedValue:)` overload resolution, rather than the type of the argument.

---

<div class="post-metadata">

**Author:** ![curt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/curt/32/1961_2.png) [@curt](https://forums.swift.org/u/curt)\
**Post date:** [February 25, 2021, 3:40pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/16 "2021-02-25T15:40:48Z")

</div>

> [@hborla](#):
>
> > [@xAlien95](#):
> >
> > These quotes seem in contradiction to me:
> > 
> > > > [@](#):
> > > >
> > > > Though the property wrapper is initialized at the call-site, the argument type _ **cannot** _ impact overload resolution of `init(wrappedValue:)` and `init(projectedValue:)` .
> > > 
> > > > [@](#):
> > > >
> > > > Overload resolution will choose which `init(wrappedValue:)` to call based on the static type of the parameter at the declaration of the property wrapper attribute [...]
> 
> There is a difference between the parameter type and the argument type. For example:
> 
> ```swift
> func generic<T>(value: T) {}
> 
> generic(value: 10)
> 
> ```
> 
> The type of the parameter is generic type `T` , and the type of the argument is `Int` . In this revision, the type of the parameter will impact `init(wrappedValue:)` overload resolution, rather than the type of the argument.

This was the one section of the revised pitch that I found confusing. Thanks for clarifying here.

Do I understand correctly that `generic` Itself could be overloaded to propagate the wrapper’s overloading to caller code?

```swift
func generic(value: Void) {}

generic(value: ()) // now calls LateInitialized’s “Value == Void” constrained initializer

```

If so, it would be great to extend the example with that. That is, after the current example add something like “Author’s can select between overloaded initializers by providing similar overloads in their declarations.”

—-  
Stepping back, thanks for all the iteration on this! I’m thrilled with where this is ending up.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 25, 2021, 9:26pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/17 "2021-02-25T21:26:55Z")

</div>

> [@curt](#):
>
> Do I understand correctly that `generic` Itself could be overloaded to propagate the wrapper’s overloading to caller code? [...] If so, it would be great to extend the example with that.

Yep, that's right! I'll add an example of this to the proposal.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [February 26, 2021, 3:30pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/18 "2021-02-26T15:30:44Z")

</div>

I'm still not sold that supporting argument wrapper for Impl wrappers is a good idea, especially when local var wrapper has just been rolled out. Nonetheless, that's a disagreement I can (reluctantly) work with.

* * *

Have we considered other categorization heuristic? Given that we know exactly which `init` is possible at function decl (only the corresponding `init(wrapppedValue:)` and `init(projectedValue:)`), we could choose between Impl wrapper and API wrapper at func decl site. That would double the type checking required (not exponentiating it thankfully), but depending on how one spin it, it could be either a footgun or a feature.

* * *

I'm glad that we now infer the `init` from the decl instead of call site. I've been thinking that the old behaviour is weird and unintuitive all this time.

* * *

> Property wrapper attributes can only be used on parameters in overridden functions or protocol witnesses if the original has the same property wrapper attributes.

This should be restricted to only API wrapper.

* * *

How does it work with implementation-detail wrapper w/ `#line` in the arguments? Do they just use the line of function decl? Maybe we should treat them as API wrapper, but `Assert` is not making this easy!

* * *

> [@DevAndArtist](#):
>
> we would just copy them into a backing storage which happens to be function local instead being an immutable parameter.

That's largely the reason we remove `var` in SE-0003. It gets confused w/ `inout` semantic. And well, supporting wrapped `inout` is also in the future direction.

Regardless, I think it's more inline with wrapping _non-mutating_ `let` local variables, which doesn't exist (I'm sure this time!).

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [February 26, 2021, 8:07pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/19 "2021-02-26T20:07:45Z")

</div>

> [@Lantua](#):
>
> Have we considered other categorization heuristic? Given that we know exactly which `init` is possible at function decl (only the corresponding `init(wrapppedValue:)` and `init(projectedValue:)` ), we could choose between Impl wrapper and API wrapper at func decl site. That would double the type checking required (not exponentiating it thankfully), but depending on how one spin it, it could be either a footgun or a feature.

Just to clarify, for `init(wrappedValue:)` and `init(projectedValue:)`, you're suggesting to 1) type check in the context of the defining module of the property wrapper to determine whether or not the wrapper can be API, and then 2) type check in the context of the defining module of the function to determine the actual initializer that will get called? I thought about that briefly. One issue that I thought of is if overload resolution chooses an `@autoclosure` `init(wrappedValue:)` in the module defining the wrapper but overload resolution chooses a regular `init(wrappedValue:)` in the module defining the function.

EDIT: This also sounds like a really complicated type checking rule to think through as a user.

> [@Lantua](#):
>
> > Property wrapper attributes can only be used on parameters in overridden functions or protocol witnesses if the original has the same property wrapper attributes.
> 
> This should be restricted to only API wrapper.

Agreed. I'll clarify in the proposal.

> [@Lantua](#):
>
> How does it work with implementation-detail wrapper w/ `#line` in the arguments? Do they just use the line of function decl? Maybe we should treat them as API wrapper, but `Assert` is not making this easy!

Yeah, the magic literals like `#file` and `#line` will use the context of the function declaration. It's certainly possible to look for magic literals in default arguments to the wrapper initializers, but promoting a wrapper to API based on default arguments feels like it could be unexpected...

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [February 26, 2021, 11:03pm UTC](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040/20 "2021-02-26T23:03:36Z")

</div>

**§Restrictions on API-level property-wrapper parameters**

> Non-instance methods cannot use property wrappers that require the enclosing `self` subscript.

Is this referring to the static `subscript(instanceSelf:wrapped:storage:)`, which was a future direction of [SE-0258](https://github.com/apple/swift-evolution/blob/main/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type)?

[Next page](https://forums.swift.org/t/pitch-5-se-0293-extend-property-wrappers-to-function-and-closure-parameters/45040.md?page=2)
