<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Josh,<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 2:35 PM, Josh Avant via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">Currently, when a reference-type adopts a protocol with a function declared as `mutating`, the reference-type's implementation cannot call that function internally. This is because the compiler enforces an immutable `self` pointer value, and the `mutating` qualifier implies that the function implementation may mutate that `self` pointer value.</div><div class=""><br class=""></div><div class="">However, there seems to be a number of fairly reasonable situations where a reference-type implementation of these `mutating` functions may only want to mutate properties owned by `self`, but not the actual `self` pointer value.</div><div class=""><br class=""></div></div></div></blockquote><div><br class=""></div></div><div>Consider this usage of the code you show below:</div><div><br class=""></div><div>var s: RandomDataTransformable = NumberSource_Struct()</div><div>var ss = s</div><div><br class=""></div><div>s.addRandomData()</div><div>// ss.data unchanged</div><div><br class=""></div><div>var c: RandomDataTransformable = NumberSource_ClassDeclaration()</div><div>var cc = c</div><div><br class=""></div><div>c.addRandomData()</div><div>// cc.data changed!</div><div><br class=""></div><div>It seems it would be difficult to write fully generic code with a protocol that has this behavior, because you cannot rely on value semantics at all. To implement ‘mutating’ class methods correctly, you would in fact have to create a new class instance and re-assign to self every time, to preserve old references, since mutating the old value might break users of the protocol that are written as if the witness was a value type. This seems to defeat the whole purpose of using a reference type in fact.</div><div><br class=""></div><div>It seems that if you really know what you’re doing, you can define a one-element struct that conforms to the protocol and contains the reference. This is in fact how Array, Dictionary and Set implement copy-on-write under the hood.</div><div><br class=""></div><div>For this reason I’m in favor of going in the opposite direction, and prohibiting classes from conforming to protocols with mutating requirements.</div><div><br class=""></div><div>Now that I think about it, setters in protocols have the same issue with confusing behavior from code that expects value semantics. Hmm...</div><div><br class=""></div><div>Slava</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">Consider this toy example:</div><div class=""><br class=""></div><div class="">```</div><div class="">import Foundation</div><div class=""><br class=""></div><div class="">protocol RandomDataTransformable {</div><div class="">&nbsp; &nbsp; typealias TransformableType</div><div class="">&nbsp; &nbsp; var data: [TransformableType] { get set }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; mutating func addRandomData()</div><div class="">}</div><div class=""><br class=""></div><div class="">extension RandomDataTransformable where TransformableType == Int {</div><div class="">&nbsp; &nbsp; mutating func addRandomData() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; let random = Int(arc4random_uniform(6) + 1)</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; data.append(random)</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">/////</div><div class=""><br class=""></div><div class="">// VALID</div><div class="">struct NumberSource_Struct : RandomDataTransformable {</div><div class="">&nbsp; &nbsp; typealias TransformableType = Int</div><div class="">&nbsp; &nbsp; var data: [Int] = []</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; mutating func addData() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; addRandomData()</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">// VALID</div><div class="">class NumberSource_ClassDeclaration: NSObject, RandomDataTransformable {</div><div class="">&nbsp; &nbsp; typealias TransformableType = Int</div><div class="">&nbsp; &nbsp; var data: [Int] = []</div><div class="">}</div><div class=""><br class=""></div><div class="">var numberSource = NumberSource_ClassDeclaration()</div><div class="">numberSource.addRandomData()</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">// INVALID</div><div class="">class NumberSource_ClassImplementation: NSObject, RandomDataTransformable {</div><div class="">&nbsp; &nbsp; typealias TransformableType = Int</div><div class="">&nbsp; &nbsp; var data: [Int] = []</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func addData() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.addRandomData() // Compiler Error: Cannot use mutating member on immutable value: 'self' is immutable</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class="">```</div><div class=""><br class=""></div><div class="">Even despite the fact that the default implementation for `addRandomData` does not mutate the `self` pointer value, reference-type implementations are unable to call that function internally, since it is marked as `mutating`.</div><div class=""><br class=""></div><div class="">Perhaps confusingly, `addRandomData` may be called by externally, by objects which own instances of the reference-type (even though, again, it may not called internally by the implementation, itself).</div><div class=""><br class=""></div><div class="">Currently, the only solution to allow reference-type implementations to call the sample `addRandomData` implementation internally is to qualify the whole `RandomDataTransformable` protocol as `class`. The downside here is that this takes an otherwise perfectly reference- and struct-compatible protocol + extension implementation and restricts it to only apply to classes, decreasing overall code reusability.</div><div class=""><br class=""></div><div class="">My proposal would be to introduce an intermediate mutation qualifier that applies when protocols are adopted by reference-types. The qualifier would specify that the `self` pointer value itself may not be mutated, but `self`'s properties may be, as appropriate.</div><div class=""><br class=""></div><div class="">Thoughts, feedback on this?</div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=NLTid1W7V2mxBEfr5Y3KfTntaxSmOQp5vjACZc9Eh1-2BFIYdRmV5ot9fT4ftsWsBCv8Vas50TXVxoolCBFutin5Lk6kNTL2PmRey5muGRZ6M5Zv8-2ByguVtgY5xsy7lh8gYupEkZg-2B-2FAowe3ZoDIbTW6QZkCDQlt3EFyXG06qf0zLdm2T6NbYYBSmYqSJgptmeOt1-2Brm2Q0TwYnNmWPXXVobDA3BoDJdo8H4LEXU9Ng68-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>