| // 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() | |
| } |