<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=""><div><blockquote type="cite" class=""><div class="">On Dec 9, 2015, at 6:09 PM, David Farler via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: Menlo-Regular;" class="">[Joe, Roman, sorry for resend, I got the e-mail group wrong]</span></div><span style="font-family: Menlo-Regular;" class=""><div class=""><span style="font-family: Menlo-Regular;" class=""><br class=""></span></div>In SuperMethodInst's verifier, we have:</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">require(CMI-&gt;getType() == TC.getConstantType(CMI-&gt;getMember()),</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"result type of super_method must match type of method");</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">I think this assumption was valid when we only allowed super_method on foreign classes, without needing to worry about reabstractions. Now that we're allowing super_method with operands of native class type which can be generic, does this check make sense anymore?</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">Consider the following:</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">class Parent&lt;A&gt; {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;let x: A</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;required init(x: A) { self.x = x }</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">}</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">class Child : Parent&lt;String&gt; {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;required init(x: String) {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;&nbsp;&nbsp;super.init(x: x)</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">&nbsp;}</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">}</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">class Grandchild : Child {}</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">Here, the vtable thunks for their initializers have respective types:</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) &lt;T&gt; (@in T, @owned Base&lt;T&gt;) -&gt; @owned Base&lt;T&gt;</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@in String, @owned Child) -&gt; @owned Child</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@in String, @owned Grandchild) -&gt; @owned Grandchild</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">However, the real backing implementations have these respective types:</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) &lt;T&gt; (@in T, @owned Base&lt;T&gt;) -&gt; @owned Base&lt;T&gt;</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@owned String, @owned Child) -&gt; @owned Child</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@owned String, @owned Grandchild) -&gt; @owned Grandchild</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">So, Child and Grandchild have abstraction differences because their initializers aren't generic. When I make a super_method instruction, the constant appears to always point to the backing implementation, not the thunk, so I needed to get the overridden vtable entry from the constant and I think that's reasonable. That gives me:</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">super_method %10 : $Child, #Base.init!initializer.1 : &lt;T&gt; Base&lt;T&gt;.Type -&gt; (x: T) -&gt; Base&lt;T&gt; , $@convention(method) &lt;τ_0_0&gt; (@in τ_0_0, @owned Base&lt;τ_0_0&gt;) -&gt; @owned Base&lt;τ_0_0&gt;</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">and</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">super_method %6 : $Grandchild, #Child.init!initializer.1 : Child.Type -&gt; (x: String) -&gt; Child , $@convention(method) (@in String, @owned Child) -&gt; @owned Child</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">which look good to me.</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">With my changes today to fix generic substitutions of partial super methods and getting the right type from the vtable, if I disable that verifier check, devirtualization works correctly with super_method instructions.</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">Is this a problem with SILDeclRef or is this check simply no longer valid in the verifier? If so, I wonder what the suitable replacement check should be. Maybe something like:</span><br style="font-family: Menlo-Regular;" class=""></div></div></blockquote><div><br class=""></div>I’d look at the verifier for ClassMethodInst. &nbsp;It turns out that TypeConverter has a getConstantOverrideType that lowers according to the overridden abstraction pattern.</div><div><br class=""></div><div>John.</div></body></html>