| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package b |
| |
| import "./a" |
| |
| type T struct{ a.T } |
| |
| func (T) m() { println("ok") } |
| |
| // The compiler used to not pay attention to package for non-exported |
| // methods when statically constructing itabs. The consequence of this |
| // was that the call to b.F1(b.T{}) in c.go would create an itab using |
| // a.T.m instead of b.T.m. |
| func F1(i interface{ m() }) { i.m() } |
| |
| // The interface method calling convention depends on interface method |
| // sets being sorted in the same order across compilation units. In |
| // the test case below, at the call to b.F2(b.T{}) in c.go, the |
| // interface method set is sorted as { a.m(); b.m() }. |
| // |
| // However, while compiling package b, its package path is set to "", |
| // so the code produced for F2 uses { b.m(); a.m() } as the method set |
| // order. So again, it ends up calling the wrong method. |
| // |
| // Also, this function is marked noinline because it's critical to the |
| // test that the interface method call happen in this compilation |
| // unit, and the itab construction happens in c.go. |
| // |
| //go:noinline |
| func F2(i interface { |
| m() |
| a.I // embeds m() from package a |
| }) { |
| i.m() |
| } |