<div dir="ltr">I'm implementing a COW big int type but am running into problems with non-mutating functions (e.g. the + operator). Simplified example code below shows AFAIK the default way to implement COW, but the non-mutating method doesn't identify the reference as unique (even with -O), resulting in a needless copy.<div><br></div><div>I've tried everything I could think of, but only inout parameters seem to work. How does the standard library do this, for e.g. String + String?<br><div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">struct</span><span style="font-variant-ligatures:no-common-ligatures"> Foo {</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo"><span style="font-variant-ligatures:no-common-ligatures;white-space:pre"><font color="#424242"> </font></span><span style="color:rgb(2,35,192);font-variant-ligatures:no-common-ligatures">var</span><span style="color:rgb(66,66,66);font-variant-ligatures:no-common-ligatures"> storage = Storage()</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>class</span><span style="font-variant-ligatures:no-common-ligatures"> Storage { </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">var</span><span style="font-variant-ligatures:no-common-ligatures"> x = </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(51,51,51)">0</span><span style="font-variant-ligatures:no-common-ligatures"> }</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><br></span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"> init(_ x: Int) { storage.x = x }</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>mutating</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">func</span><span style="font-variant-ligatures:no-common-ligatures"> negate() {</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span></span><span style="white-space:pre"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">if</span><span style="font-variant-ligatures:no-common-ligatures"> !isKnownUniquelyReferenced(&storage) {</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><span style="white-space:pre"> </span>print(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(153,18,1)">"Copy"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><span style="white-space:pre"> </span>}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><span style="white-space:pre"> </span>storage.x = -storage.x</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span style="white-space:pre"> </span>}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>func</span><span style="font-variant-ligatures:no-common-ligatures"> negated() -> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(27,178,173)">Foo</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(166,166,166)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(66,66,66)"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span></span><span style="color:rgb(66,66,66);white-space:pre"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">var</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(66,66,66)"> result = </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">self</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(66,66,66)"> </span><span style="font-variant-ligatures:no-common-ligatures">// This counts as a second reference</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><span style="white-space:pre"> </span>result.negate()</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span class="gmail-Apple-tab-span" style="white-space:pre"> </span></span><span style="white-space:pre"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">return</span><span style="font-variant-ligatures:no-common-ligatures"> result</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span style="white-space:pre"> </span>}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures">}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)">func</span><span style="font-variant-ligatures:no-common-ligatures"> test() {</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>var</span><span style="font-variant-ligatures:no-common-ligatures"> a = Foo(5)</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span style="white-space:pre"> </span>a.negate()</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span style="white-space:pre"> </span>print(a.storage.x)</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>let</span><span style="font-variant-ligatures:no-common-ligatures"> b = Foo(5)</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(2,35,192)"><span style="color:rgb(66,66,66);white-space:pre"> </span>let</span><span style="font-variant-ligatures:no-common-ligatures"> c = b.negated()</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><span style="white-space:pre"> </span>print(c</span>.storage.x)</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures">}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)">
</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures">test()</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><span style="font-variant-ligatures:no-common-ligatures"><br></span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo;color:rgb(66,66,66)"><b>Output</b></p><p style="margin:0px;font-size:10px;line-height:normal;font-family:monaco"><span style="font-variant-ligatures:no-common-ligatures;background-color:rgb(255,255,255)"><font color="#000000">-5</font></span></p><p style="margin:0px;font-size:10px;line-height:normal;font-family:monaco"><span style="font-variant-ligatures:no-common-ligatures;background-color:rgb(255,255,255)"><font color="#000000">Copy</font></span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:menlo">
</p><p style="margin:0px;font-size:10px;line-height:normal;font-family:monaco"><span style="font-variant-ligatures:no-common-ligatures;background-color:rgb(255,255,255)"><font color="#000000">-5</font></span></p></div><div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div></div></div></div>