<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Dec 20, 2017, at 3:56 PM, Raj Barik &lt;<a href="mailto:rkbarik@gmail.com" class="">rkbarik@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Thank you Arnold &amp; Slava! The protocol devirtualizer pass works fine now for most cases. I should be creating a PR soon (after some more testing).<div class=""><br class=""></div><div class="">I am thinking about extending this to Optional types as well, i.e.,&nbsp;</div></div></div></blockquote><div><br class=""></div>I’m not sure if its possible in the general case. What you might think of doing is rewriting this into a function that takes an Optional&lt;T&gt; where T : SumProtocol. But the trouble is if the value of ‘a’ is nil, then there’s no concrete type to bind to the type parameter T at runtime. What you really want is a way to write</div><div><br class=""></div><div>enum WeirdOptional {</div><div>&nbsp; case &lt;T&gt; some(T)</div><div>&nbsp; case none</div><div>}</div><div><br class=""></div><div>But we don’t allow this.</div><div><br class=""></div><div>I think even without handling optionals though, this optimization definitely has value.</div><div><br class=""></div><div>Are you implementing it as a separate pass, or is it part of function signature specialization?</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=""><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class="">@inline(never) internal func wrap_inc_optional(a:SumProtocol?, val:Int) -&gt; Int?{</div><div style="font-size:12.8px" class="">&nbsp;return a?.increment(i:val)</div><div style="font-size:12.8px" class="">}</div></div><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class="">The generated SIL looks something like this:</div><div style="font-size:12.8px" class=""><br class=""></div><div class=""><div class=""><div class=""><span style="font-size:12.8px" class="">sil hidden [noinline] @_T04main21wrap_inc_optionalSiSgAA11SumProtocol_pSg1a_Si3valtF : $@convention(thin) (@owned Optional&lt;SumProtocol&gt;, Int) -&gt; Optional&lt;Int&gt; {</span></div><div class=""><span style="font-size:12.8px" class="">// %0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// users: %11, %4, %7, %2</span></div><div class=""><span style="font-size:12.8px" class="">// %1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// users: %10, %3</span></div><div class=""><span style="font-size:12.8px" class="">bb0(%0 : $Optional&lt;SumProtocol&gt;, %1 : $Int):</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; debug_value %0 : $Optional&lt;SumProtocol&gt;, let, name "a", argno 1 // id: %2</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; debug_value %1 : $Int, let, name "val", argno 2 // id: %3</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp;<font color="#ff0000" class=""> switch_enum %0 : $Optional&lt;SumProtocol&gt;, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1 // id: %4</font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class=""><br class=""></font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class="">bb1:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Preds: bb0</font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class="">&nbsp; %5 = enum $Optional&lt;Int&gt;, #Optional.none!enumelt // user: %6</font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class="">&nbsp; br bb3(%5 : $Optional&lt;Int&gt;)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// id: %6</font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class=""><br class=""></font></span></div><div class=""><span style="font-size:12.8px" class=""><font color="#ff0000" class="">bb2:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Preds: bb0</font></span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; %7 = unchecked_enum_data %0 : $Optional&lt;SumProtocol&gt;, #Optional.some!enumelt.1 // user: %8</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; %8 = open_existential_ref %7 : $SumProtocol to $@opened("F0395A0A-E5DE-11E7-A06A-420039484801") SumProtocol // users: %10, %10, %9</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; %9 = witness_method $@opened("F0395A0A-E5DE-11E7-A06A-420039484801") SumProtocol, #SumProtocol.increment!1 : &lt;Self where Self : SumProtocol&gt; (Self) -&gt; (Int) -&gt; Int, %8 : $@opened("F0395A0A-E5DE-11E7-A06A-420039484801") SumProtocol : $@convention(witness_method) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (Int, @guaranteed τ_0_0) -&gt; Int // type-defs: %8; user: %10</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; %10 = apply %9&lt;@opened("F0395A0A-E5DE-11E7-A06A-420039484801") SumProtocol&gt;(%1, %8) : $@convention(witness_method) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (Int, @guaranteed τ_0_0) -&gt; Int // type-defs: %8; user: %12</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; release_value %0 : $Optional&lt;SumProtocol&gt;&nbsp; &nbsp; &nbsp; &nbsp;// id: %11</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; %12 = enum $Optional&lt;Int&gt;, #Optional.some!enumelt.1, %10 : $Int // user: %13</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; br bb3(%12 : $Optional&lt;Int&gt;)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // id: %13</span></div><div class=""><span style="font-size:12.8px" class=""><br class=""></span></div><div class=""><span style="font-size:12.8px" class="">// %14&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // user: %15</span></div><div class=""><span style="font-size:12.8px" class="">bb3(%14 : $Optional&lt;Int&gt;):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Preds: bb1 bb2</span></div><div class=""><span style="font-size:12.8px" class="">&nbsp; return %14 : $Optional&lt;Int&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// id: %15</span></div></div></div><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class="">The above branching code (in red) in the SIL makes it non-trivial to abstract out the non-nil path to a generic outlined method while keeping the branching code in the thunk and also its not clear if the SILCombiner peephole optimizer will actually come into affect for this scenario (because of the branching code getting inlined in the caller).&nbsp; It also gets more complicated if there are more than one optional types as parameter to wrap_inc_optional. Any clue on how one can handle optional types for devirtualization or if there are any existing transformations in Swift compiler that can help implement this easily? Thanks.</div><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class="">-R</div><div style="font-size:12.8px" class=""><br class=""></div><div style="font-size:12.8px" class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Wed, Dec 13, 2017 at 3:28 PM, Arnold Schwaighofer <span dir="ltr" class="">&lt;<a href="mailto:aschwaighofer@apple.com" target="_blank" class="">aschwaighofer@apple.com</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You don’t need a second open_existential_ref in the _wrap_inc&lt;T: SumProtocol&gt; function. It should look something like this:<br class="">
<br class="">
sil @_wrap_inc : $@convention(thin) &lt;T where T : SumProtocol&gt; (@owned T, Int) -&gt; Int {<br class="">
bb0(%0 : $T, %1 : $Int):<br class="">
&nbsp; %5 = witness_method $T, #SumProtocol.inc!1 : &lt;Self where Self : SumProtocol&gt; (Self) -&gt; (Int) -&gt; Int : $@convention(witness_method: SumProtocol) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (Int, @guaranteed τ_0_0) -&gt; Int<br class="">
&nbsp; %6 = apply %5&lt;T&gt;(%1, %0) : $@convention(witness_method: SumProtocol) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (Int, @guaranteed τ_0_0) -&gt; Int<br class="">
&nbsp; destroy_value %0 : $T<br class="">
&nbsp; return %6 : $Int<br class="">
}<br class="">
<br class="">
In the other function it looks like you need to apply the proper substitution list to the apply instruction:<br class="">
<span class=""><br class="">
sil hidden [thunk] [always_inline] @_T04main8wrap_<wbr class="">incSiAA11SumProtocol_p1a_<wbr class="">Si3valtF : $@convention(thin) (@owned SumProtocol, Int) -&gt; Int {<br class="">
</span><span class="">bb0(%0 : $SumProtocol, %1 : $Int):<br class="">
&nbsp; // function_ref specialized wrap_inc(a:val:)<br class="">
&nbsp; %2 = function_ref @_T04main8wrap_<wbr class="">incSiAA11SumProtocol_p1a_<wbr class="">Si3valtFTf4nn_n<br class="">
</span><span class="">&nbsp; %3 = open_existential_ref %0 : $SumProtocol to $@opened("E6196082-DF72-11E7-<wbr class="">8C84-420039484801") SumProtocol<br class="">
</span><span class="">&nbsp; %4 = apply %2&lt;τ_0_0&gt;(%3, %1) : $@convention(thin) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (@owned τ_0_0, Int) -&gt; Int // user: %5<br class="">
<br class="">
</span>τ_0_0 should have been substituted by the opened type: $@opened("E6196082-DF72-11E7-<wbr class="">8C84-420039484801”) SumProtocol.<br class="">
<span class=""><br class="">
&nbsp; %3 = open_existential_ref %0 : $SumProtocol to $@opened("E6196082-DF72-11E7-<wbr class="">8C84-420039484801") SumProtocol<br class="">
</span>&nbsp; %4 = apply %2&lt;@opened("E6196082-DF72-<wbr class="">11E7-8C84-420039484801”) SumProtocol&gt;(%3, %1) : $@convention(thin) &lt;τ_0_0 where τ_0_0 : SumProtocol&gt; (@owned τ_0_0, Int) -&gt; Int<br class="">
<br class="">
<br class="">
Probably, you have to pass the right SubstitutionList to the createApplyInst call.<br class="">
<br class="">
<br class="">
The peephole that propagates types from an init existential Slava referred to is here:<br class="">
<br class="">
&nbsp; <a href="https://github.com/apple/swift/blob/master/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp#L974" rel="noreferrer" target="_blank" class="">https://github.com/apple/<wbr class="">swift/blob/master/lib/<wbr class="">SILOptimizer/SILCombiner/<wbr class="">SILCombinerApplyVisitors.cpp#<wbr class="">L974</a> (SILCombiner::<wbr class="">propagateConcreteTypeOfInitExi<wbr class="">stential)<br class="">
<br class="">
Here is a test case that shows how the type from the init existential is propagated (instead of a generic type ’T’ as in the test case, in your case it would be the class type SumClass):<br class="">
<br class="">
&nbsp; <a href="https://github.com/apple/swift/blob/master/test/SILOptimizer/sil_combine.sil#L2569" rel="noreferrer" target="_blank" class="">https://github.com/apple/<wbr class="">swift/blob/master/test/<wbr class="">SILOptimizer/sil_combine.sil#<wbr class="">L2569</a><br class="">
<div class="HOEnZb"><div class="h5"><br class="">
&gt; On Dec 13, 2017, at 11:39 AM, Raj Barik via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:<br class="">
&gt;<br class="">
&gt; Slava,<br class="">
&gt;<br class="">
&gt; I have two (clarification) questions in your proposed implementation:<br class="">
&gt;<br class="">
&gt; Original Function:<br class="">
&gt; @inline(never) internal func wrap_inc(a:SumProtocol, val:Int) -&gt; Int{<br class="">
&gt;&nbsp; return a.increment(i:val)<br class="">
&gt; }<br class="">
&gt; Transformed code:<br class="">
&gt; @inline(always) internal func wrap_inc(a: SumProtocol, val: Int) -&gt; Int {<br class="">
&gt;&nbsp; &nbsp;// opening an existential cannot be expressed in Swift, but it can in SIL…<br class="">
&gt;&nbsp; &nbsp;let _a = a open as T<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp;return _wrap_inc(_a, val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; @inline(never) internal func _wrap_inc&lt;T : SumProtocol&gt;(_a:T, val:Int) -&gt; Int{<br class="">
&gt;&nbsp; return _a.increment(i:val)<br class="">
&gt; }<br class="">
&gt; ******************************<wbr class="">******************************<wbr class="">****************************<br class="">
&gt; In the above code sequence, did you mean that "let _a = a open as T" opens "a:SumProtocol" using open_existential_ref&nbsp; instruction as "SumClass" which is the concrete type of a or it is opened as the "$@opened SumProtocol". In both cases, the open_existential_ref in the original function is still there and giving rise to opening the existential twice. Did you also intended that the _wrap_inc function is rewritten to eliminate the open_existential_ref as well (this is more complicated if the protocol is passed down a call chain)? So, I do not really understand what the "let _a = a open as T" is suggesting. The other part of the confusion is about the peephole optimization which optimizes the code sequence consisting of the creation of object for SumClass and then the init_existential_ref and followed by the open_existential_ref. Can you clarify?<br class="">
&gt;<br class="">
&gt; Thanks.<br class="">
&gt;<br class="">
&gt;<br class="">
&gt; On Wed, Nov 29, 2017 at 1:43 PM, Slava Pestov &lt;<a href="mailto:spestov@apple.com" class="">spestov@apple.com</a>&gt; wrote:<br class="">
&gt; Hi Raj,<br class="">
&gt;<br class="">
&gt; The way I would approach this problem is first, turn a function taking a protocol value into one taking a protocol-constrained generic parameter. So<br class="">
&gt;<br class="">
&gt; @inline(never) internal func wrap_inc(a:SumProtocol, val:Int) -&gt; Int{<br class="">
&gt;&nbsp; return a.increment(i:val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; Would become<br class="">
&gt;<br class="">
&gt; @inline(always) internal func wrap_inc(a: SumProtocol, val: Int) -&gt; Int {<br class="">
&gt;&nbsp; &nbsp;// opening an existential cannot be expressed in Swift, but it can in SIL…<br class="">
&gt;&nbsp; &nbsp;let _a = a open as T<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp;return _wrap_inc(_a, val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; @inline(never) internal func _wrap_inc&lt;T : SumProtocol&gt;(_a:T, val:Int) -&gt; Int{<br class="">
&gt;&nbsp; let a: SomeProtocol = _a<br class="">
&gt;&nbsp; return a.increment(i:val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; (Note that the existing function signature specialization pass performs a similar transformation where it creates a new function with the same body as the old function but a different signature, and replaces the old function with a short thunk that transforms arguments and results and calls the new function.)<br class="">
&gt;<br class="">
&gt; At this point, the existing “initialize existential with concrete type” peephole in the SILCombiner should eliminate the existential (but the peephole doesn’t work in 100% of cases yet):<br class="">
&gt;<br class="">
&gt; @inline(always) internal func wrap_inc(a: SumProtocol, val: Int) -&gt; Int {<br class="">
&gt;&nbsp; &nbsp;// opening an existential cannot be expressed in Swift, but it can in SIL…<br class="">
&gt;&nbsp; &nbsp;let _a = a open as T<br class="">
&gt;<br class="">
&gt;&nbsp; &nbsp;return _wrap_inc(_a, val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; @inline(never) internal func _wrap_inc&lt;T : SumProtocol&gt;(_a:T, val:Int) -&gt; Int{<br class="">
&gt;&nbsp; return _a.increment(i:val)<br class="">
&gt; }<br class="">
&gt;<br class="">
&gt; Now, if I have a call to wrap_inc somewhere,<br class="">
&gt;<br class="">
&gt; internal let magic:SumProtocol = SumClass(base:10)<br class="">
&gt; _ = wrap_inc(magic)<br class="">
&gt;<br class="">
&gt; Then the optimizer will inline the thunk, giving you a call to _wrap_inc. The existential value built from the SumClass instance is immediately opened so it will be peepholed away. At this point you have a call of a generic function _wrap_inc with a concrete type SumClass, and the generic specializer can produce a specialization of it.<br class="">
&gt;<br class="">
&gt; Notice how this approach combines several existing optimizations and only requires adding a relatively simple new transformation, and possibly improving some of the existing optimizations to cover more cases.<br class="">
&gt;<br class="">
&gt; Slava<br class="">
&gt;<br class="">
&gt;&gt; On Nov 29, 2017, at 11:30 AM, Raj Barik via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:<br class="">
&gt;&gt;<br class="">
&gt;&gt; Hi,<br class="">
&gt;&gt;<br class="">
&gt;&gt; I am thinking about writing a Protocol Devirtualizer Pass that specializes functions that take Protocols as arguments to transform them with concrete types instead of protocol types when the concrete types can be determined statically by some compiler analysis. This is the first step of the transformation that I am proposing. My goal is to extend this to eliminate the original function implementation and also to remove the corresponding protocol type (by deleting it from the witness table), if possible. For simple cases, where the protocol is only used for mocking for example and that there is just one class that conforms to it, we should be able to eliminate the protocol altogether. This is the second and final step of the transformation. Does anyone see any issues with both these steps? Arnold from Apple pointed out that there might be demangling issues when the protocol is eliminated. Any ideas on how to fix the demangling issues? Moreover, would such a pass be helpful to Swift folks?<br class="">
&gt;&gt;<br class="">
&gt;&gt; Original code:<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt; protocol SumProtocol: class {<br class="">
&gt;&gt;&nbsp; &nbsp;func increment(i:Int)&nbsp; -&gt; Int<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal class SumClass: SumProtocol {<br class="">
&gt;&gt;&nbsp; &nbsp;var a:Int<br class="">
&gt;&gt;&nbsp; &nbsp;init(base:Int) {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp;self.a = base<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt;&nbsp; &nbsp;func increment(i:Int) -&gt; Int {<br class="">
&gt;&gt;&nbsp; &nbsp; self.a += i<br class="">
&gt;&gt;&nbsp; &nbsp; return self.a<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; @inline(never) internal func wrap_inc(a:SumProtocol, val:Int) -&gt; Int{<br class="">
&gt;&gt;&nbsp; return a.increment(i:val)<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal let magic:SumProtocol = SumClass(base:10)<br class="">
&gt;&gt; print("c=\(wrap_inc(a:magic,<wbr class="">val:10))")<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt; After Step 1:<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt; protocol SumProtocol: class {<br class="">
&gt;&gt;&nbsp; &nbsp;func increment(i:Int)&nbsp; -&gt; Int<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal class SumClass: SumProtocol {<br class="">
&gt;&gt;&nbsp; &nbsp;var a:Int<br class="">
&gt;&gt;&nbsp; &nbsp;init(base:Int) {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp;self.a = base<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt;&nbsp; &nbsp;func increment(i:Int) -&gt; Int {<br class="">
&gt;&gt;&nbsp; &nbsp; self.a += i<br class="">
&gt;&gt;&nbsp; &nbsp; return self.a<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; @inline(never) internal func wrap_inc(a:SumProtocol, val:Int) -&gt; Int{<br class="">
&gt;&gt;&nbsp; return a.increment(i:val)<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; @inline(never) internal func wrap_inc_1(a:SumClass, val:Int) -&gt; Int{<br class="">
&gt;&gt;&nbsp; return a.increment(i:val)<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal let magic:SumClass = SumClass(base:10)<br class="">
&gt;&gt; print("c=\(wrap_inc_1(a:magic,<wbr class="">val:10))")<br class="">
&gt;&gt;<br class="">
&gt;&gt;<br class="">
&gt;&gt; After Step 2:<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal class SumClass {<br class="">
&gt;&gt;&nbsp; &nbsp;var a:Int<br class="">
&gt;&gt;&nbsp; &nbsp;init(base:Int) {<br class="">
&gt;&gt;&nbsp; &nbsp; &nbsp;self.a = base<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt;&nbsp; &nbsp;func increment(i:Int) -&gt; Int {<br class="">
&gt;&gt;&nbsp; &nbsp; self.a += i<br class="">
&gt;&gt;&nbsp; &nbsp; return self.a<br class="">
&gt;&gt;&nbsp; &nbsp;}<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; @inline(never) internal func wrap_inc(a:SumClass, val:Int) -&gt; Int{<br class="">
&gt;&gt;&nbsp; return a.increment(i:val)<br class="">
&gt;&gt; }<br class="">
&gt;&gt;<br class="">
&gt;&gt; internal let magic:SumClass = SumClass(base:10)<br class="">
&gt;&gt; print("c=\(wrap_inc(a:magic,<wbr class="">val:10))")<br class="">
&gt;&gt;<br class="">
&gt;&gt; Any comments/thought on this transformation?<br class="">
&gt;&gt;<br class="">
&gt;&gt; Best,<br class="">
&gt;&gt; Raj<br class="">
&gt;&gt; ______________________________<wbr class="">_________________<br class="">
&gt;&gt; swift-dev mailing list<br class="">
&gt;&gt; <a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a><br class="">
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-dev" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-dev</a><br class="">
&gt;<br class="">
&gt;<br class="">
&gt; ______________________________<wbr class="">_________________<br class="">
&gt; swift-dev mailing list<br class="">
&gt; <a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a><br class="">
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-dev" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-dev</a><br class="">
<br class="">
</div></div></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></body></html>