_modify for @propertyWrapper

Follow up to discussion at https://forums.swift.org/t/property-wrapper-causing-excessive-array-copying/.

Just had a quick look and it seems like we are synthesising a _modify accessor for a @propertyWrapper property, for example, if we have

@propertyWrapper
struct TestWrapper<ValueType> {
  var wrappedValue: ValueType
}
		
struct State {
  @TestWrapper var values: [String] = []
}

we generate a _modify accessor for values:

(accessor_decl implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19] 'anonname=0x7ffe160ae7d8' interface type='(inout State) -> () -> ()' access=internal _modify_for=values
  (parameter "self" type='State' interface type='State' inout)
  (parameter_list)
  (brace_stmt implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19]
    (yield_stmt implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19]
      (inout_expr implicit type='inout [String]'
        (member_ref_expr implicit type='@lvalue [String]' decl=test.(file).TestWrapper.wrappedValue@/Users/suyashsrijan/Desktop/test.swift:3:6 [with (substitution_map generic_signature=<ValueType> (substitution ValueType -> [String]))]
          (member_ref_expr implicit type='@lvalue TestWrapper<[String]>' decl=test.(file).State._values@/Users/suyashsrijan/Desktop/test.swift:7:19 direct_to_storage
            (declref_expr implicit type='@lvalue State' decl=test.(file).State.<anonymous>.self@/Users/suyashsrijan/Desktop/test.swift:7:19 function_ref=unapplied))))))))

However, looking at the generated SIL, we only seem to be using the setter and the _modify is nowhere to be seen (no SIL generated for it). I am going to do more digging to figure out what's going on, but I'm also wondering if I missed something obvious.

3 Likes

I wonder if this requires a change in SILGen, because I haven't quite found anything yet in Sema that could be preventing this... unless we're not correctly synthesising the _modify or the read/write/readwrite impl kind is not correctly set. I was looking at SILGenType and it seems to visit the _modify as well.

(also, do we actually use the synthesised coroutines? Looking at the test suite, all of them are using an explicit coroutine)

Oops, seems like we're not synthesising the _modify correctly! I don't know how I ended up with the previous AST (maybe I accidentally used an different test file), but I can now that the synthesised _modify isn't correct:

(accessor_decl implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19] 'anonname=0x7fd26405cbd8' interface type='(inout State) -> () -> ()' access=internal _modify_for=values
  (parameter "self" type='State' interface type='State' inout)
  (parameter_list)
  (brace_stmt implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19]
    (yield_stmt implicit range=[/Users/suyashsrijan/Desktop/test.swift:7:19 - line:7:19]
      (inout_expr implicit type='inout [String]'
        (member_ref_expr implicit type='@lvalue [String]' decl=test.(file).State.values@/Users/suyashsrijan/Desktop/test.swift:7:19 direct_to_impl
          (declref_expr implicit type='@lvalue State' decl=test.(file).State.<anonymous>.self@/Users/suyashsrijan/

It needs to yield _values.wrappedValue the same way the setter accesses it. I'll try that tomorrow!

6 Likes

I just want to say that while I don't really follow the details of this, I really appreciate that you're digging into it. :smiley:

Thank you for working on this @suyashsrijan.