<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 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->getType() == TC.getConstantType(CMI->getMember()),</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> "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<A> {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> let x: A</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> 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<String> {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> required init(x: String) {</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> super.init(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=""><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) <T> (@in T, @owned Base<T>) -> @owned Base<T></span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@in String, @owned Child) -> @owned Child</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@in String, @owned Grandchild) -> @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) <T> (@in T, @owned Base<T>) -> @owned Base<T></span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@owned String, @owned Child) -> @owned Child</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">$@convention(method) (@owned String, @owned Grandchild) -> @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 : <T> Base<T>.Type -> (x: T) -> Base<T> , $@convention(method) <τ_0_0> (@in τ_0_0, @owned Base<τ_0_0>) -> @owned Base<τ_0_0></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 -> (x: String) -> Child , $@convention(method) (@in String, @owned Child) -> @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=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">if the constant is foreign:</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> do the original check</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">else:</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> require super_method's result type == vtable entry's function type (as opposed to the backing implementation)</span><br style="font-family: Menlo-Regular;" class=""><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">David</span></body></html>