3

I wrote a simple library for serializing model data and later realized I was getting writes to my data when I was only reading. I was able to reduce the problem to the following playground snippet:

class Foo {
    init() { name = "test" }
    var name:String { didSet { print("setting name: \(self.name)") }}
}


func map(inout foo:String) {
    print("writing value: \(foo)")
}

var foo:Foo = Foo()
map(&foo.name)

The result is (to me) unexpected:

writing value: test

setting name: test

I have re-read the section on inout parameters but saw no explicit mention of copy semantics. My hunch is that the compiler is expecting the value to be overwritten and does so itself with the initial value, if no other code does so.

Does this seem expected, or a compiler bug? In my humble opinion, it is unintuitive behavior. I was not expecting an assignment, unless it originated from my code - which it did not.

To state what is hopefully obvious, the code snippet above does not need the inout param, but I had been using a common interface for reading and writing.

Community
  • 1
  • 1
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • 1
    Very interesting! Btw you can reduce it ever further: `var x = 0 { didSet { print("Setting") } }; func f(inout x : Int) {}; f(&x)` – Kametrixom Oct 06 '15 at 16:30

2 Answers2

5

I'm posting this on behalf of Joe Groff, a Swift compiler developer, on Twitter (See replies). He was very nice in answering my Tweet mentioning this question.

He says:

Inout has value-result semantics. The didSet receives the modified value at the end of the inout. It only optimizes to pass-by-reference if the difference is unobservable (modulo invalid aliasing). The Swift book is supposed to be updated with this info too.

Kametrixom
  • 14,673
  • 7
  • 45
  • 62
  • hi, any idea on this one https://stackoverflow.com/questions/60886752/swift-inout-copies-back-property-even-if-not-changed ? – Peter Lapisu Mar 27 '20 at 13:14
4

In the document:

You write an in-out parameter by placing the inout keyword at the start of its parameter definition. An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.

in-out parameter is not "call-by-reference", but "call-by-copy-restore"

rintaro
  • 51,423
  • 14
  • 131
  • 139