<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="">I did report this problem as&nbsp;<a href="https://bugs.swift.org/browse/SR-142" class="">https://bugs.swift.org/browse/SR-142</a> a couple of days ago.<div class=""><br class=""></div><div class="">Greg Titus replied:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">Looked into this briefly, and it's a lot harder than just changing the error checking, since m() has&nbsp;an implicit `inout P` first argument. Probably the solution is an automatic version of Gwendal's&nbsp;workaround: declaring a hidden `var p: P = c` and calling the method on p.<br class=""></blockquote><div class=""><br class=""></div><div class="">Gwendal Roué</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Le 11 déc. 2015 à 18:22, Josh Avant via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class="">Thanks, Kevin!<div class=""><br class=""></div><div class="">Look forward to any other feedback!<br class=""><br class="">On Thursday, December 10, 2015, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u class=""></u>




<div class=""><div class="">A couple of miscellaneous points:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">* This problem only occurs when the class inherits a default implementation of the method from a protocol extension. If the class declares the method itself, then it's no longer a mutating method and everything works fine.<br class=""></div>
<div class="">* The problem exists because mutating functions are allowed to assign to self, but methods on class types cannot assign to self, they can only mutate the properties of self. This is why we cannot simply allow the call to the inherited mutating method, as that method may reassign self.<br class=""></div>
<div class="">* Classes can still call the method, they just have to say something like<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">var this = self</span><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class=""><br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">this.callMutatingMethod()</span><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class=""><br class=""></span></div>
<div class="">&nbsp;</div>
<div class="">Yeah it's a little awkward, but it's not really all that bad for an edge case like this.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Another potential workaround requires more work on the protocol side but allows implementations to not care about the difference, which is to provide a non-mutating variant in an extension restricted by Self: AnyObject:<br class=""></div>
<div class="">&nbsp;</div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">protocol P {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; var count: Int { get set }<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; mutating func foo() -&gt; String<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">}<br class=""></span></div>
<div class="">&nbsp;</div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">extension P {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; mutating func foo() -&gt; String {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; &nbsp; &nbsp; return _mutatingFoo(&amp;self)<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; }<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">}<br class=""></span></div>
<div class="">&nbsp;</div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">extension P where Self: AnyObject {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; func foo() -&gt; String {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; &nbsp; &nbsp; var this = self<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; &nbsp; &nbsp; return _mutatingFoo(&amp;this)<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; }<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">}<br class=""></span></div>
<div class="">&nbsp;</div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">private func _mutatingFoo&lt;T: P&gt;(inout value: T) -&gt; String {<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; value.count += 1<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">&nbsp; &nbsp; return "foo"<br class=""></span></div>
<div class=""><span style="font-family:menlo,consolas,&quot;courier new&quot;,monospace,sans-serif" class="">}<br class=""></span></div>
<div class="">&nbsp;</div>
<div class="">Ultimately, I think there's some value in this proposal, but I worry about adding a new keyword to handle an edge case like this when there's workarounds available. Assuming we do add this feature, I'd suggest using something like `mutating(ish)` instead of inventing a brand new keyword (there's precedent in `private(set)`).<br class=""></div>
<div class="">&nbsp;</div>
<div class="">-Kevin Ballard</div>
<div class="">&nbsp;</div>
<div class="">On Thu, Dec 10, 2015, at 02:35 PM, Josh Avant via swift-evolution wrote:<br class=""></div>
<blockquote type="cite" 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.<br class=""></div>
<div class="">&nbsp;</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.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Consider this toy example:<br class=""></div>
<div class="">&nbsp;</div>
<div class="">```<br class=""></div>
<div class="">import Foundation<br class=""></div>
<div class="">&nbsp;</div>
<div class="">protocol RandomDataTransformable {<br class=""></div>
<div class="">&nbsp; &nbsp; typealias TransformableType<br class=""></div>
<div class="">&nbsp; &nbsp; var data: [TransformableType] { get set }<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; mutating func addRandomData()<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">extension RandomDataTransformable where TransformableType == Int {<br class=""></div>
<div class="">&nbsp; &nbsp; mutating func addRandomData() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; let random = Int(arc4random_uniform(6) + 1)<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; data.append(random)<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">/////<br class=""></div>
<div class="">&nbsp;</div>
<div class="">// VALID<br class=""></div>
<div class="">struct NumberSource_Struct : RandomDataTransformable {<br class=""></div>
<div class="">&nbsp; &nbsp; typealias TransformableType = Int<br class=""></div>
<div class="">&nbsp; &nbsp; var data: [Int] = []<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; mutating func addData() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; addRandomData()<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">// VALID<br class=""></div>
<div class="">class NumberSource_ClassDeclaration: NSObject, RandomDataTransformable {<br class=""></div>
<div class="">&nbsp; &nbsp; typealias TransformableType = Int<br class=""></div>
<div class="">&nbsp; &nbsp; var data: [Int] = []<br class=""></div>
<div class="">}<br class=""></div>
<div class="">&nbsp;</div>
<div class="">var numberSource = NumberSource_ClassDeclaration()<br class=""></div>
<div class="">numberSource.addRandomData()<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp;</div>
<div class="">// INVALID<br class=""></div>
<div class="">class NumberSource_ClassImplementation: NSObject, RandomDataTransformable {<br class=""></div>
<div class="">&nbsp; &nbsp; typealias TransformableType = Int<br class=""></div>
<div class="">&nbsp; &nbsp; var data: [Int] = []<br class=""></div>
<div class="">&nbsp;</div>
<div class="">&nbsp; &nbsp; func addData() {<br class=""></div>
<div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.addRandomData() // Compiler Error: Cannot use mutating member on immutable value: 'self' is immutable<br class=""></div>
<div class="">&nbsp; &nbsp; }<br class=""></div>
<div class="">}<br class=""></div>
<div class="">```<br class=""></div>
<div class="">&nbsp;</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`.<br class=""></div>
<div class="">&nbsp;</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).<br class=""></div>
<div class="">&nbsp;</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.<br class=""></div>
<div class="">&nbsp;</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.<br class=""></div>
<div class="">&nbsp;</div>
<div class="">Thoughts, feedback on this?<br class=""></div>
</div>
<div class=""><img style="min-height:1px!important;width:1px!important;border-top-width:0px!important;border-right-width:0px!important;border-bottom-width:0px!important;border-left-width:0px!important;margin-top:0px!important;margin-bottom:0px!important;margin-right:0px!important;margin-left:0px!important;padding-top:0px!important;padding-bottom:0px!important;padding-right:0px!important;padding-left:0px!important" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/b3b692329332b943295dfc8454c0e94db5a907328abf7ffdb39b752b54b97fc1/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e495e40563859697437636b4863644a5d4475397d223243774f6453796949736653347741767475736a48466746666a447c43607e634237716936726f43424d4c6d67507a7d686f635878564460337d22364b60753676583c6c46494d2236473c4c663139635d4a714546545e674e61653233724c6a54305f605d2232497a6a764649597c454a695543707565546d687f42384b6b6a6f426053486f425c696e434253576b6c6847517159315f464f613272547232675b6f4774613a4331464b67685a76726f474466615d23344d23344/open" class=""><br class=""></div>
<div class=""><u class="">_______________________________________________</u><br class=""></div>
<div class="">swift-evolution mailing list<br class=""></div>
<div class=""><a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a><br class=""></div>
<div class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div>
</blockquote><div class="">&nbsp;</div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=UqrBeBSFFZ3qCW2UhjXSFiQVUl3B3t-2Bn3RK9F3k22XngI33MPlIGaYAqG-2BZl0C02P7ydD3ZilX0-2Fz65yf096uIncFm36rZs2F-2Bc-2FjfrvarUgkYU9Q2P78swEkt9ToUvCJ-2FmXoixaOQ7YMaXXDUaHR0WkkpLVEMMuJ49f2HnDuUFNDiYhBqbTQacaW7XD60T0-2FrGrFfqpHA9fnR4QNGCLqbClLLYVV0EFpShu8Y5oCI4-3D" alt="" width="1" height="1" border="0" style="min-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="">
</div>


</blockquote></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=GUvuDT95GpxW2sIYHiKg6obX3uIIobaj9awaKuut6Z-2B4uNa4UWxdQHOnfUOvXBEOH1qMYb9BmHzrma5xexwQKwNchCUH1jIhpqlvAa4fstDucIXfvpnJXkjd-2BdtyzYmRfZgBzc61-2FnXIyCAC6SR-2F3d2N0vXsTrLsvw52FjP-2Fw30dYciwuaDOzjnibE0I9psS6iTJ-2FOkcuMiAkF90PX7XotVSx2lbSIVYFIOK-2FVI3EV0-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></div></body></html>