mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
go.tools/ssa: fix bug in makeBridgeMethod for promoted interfaces.
The method index was hard-coded to zero, which works some of the time. Apparently I just forgot to implement the method-table lookup... Added regression test. R=gri CC=golang-dev https://golang.org/cl/9916043
This commit is contained in:
parent
838e9a8987
commit
1f2812fe9b
@ -20,7 +20,7 @@ type PackageInfo struct {
|
||||
// Type-checker deductions.
|
||||
types map[ast.Expr]types.Type // inferred types of expressions
|
||||
constants map[ast.Expr]exact.Value // values of constant expressions
|
||||
idents map[*ast.Ident]types.Object // resoved objects for named entities
|
||||
idents map[*ast.Ident]types.Object // resolved objects for named entities
|
||||
typecases map[*ast.CaseClause]*types.Var // implicit vars for single-type typecases
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ func (info *PackageInfo) TypeOf(e ast.Expr) types.Type {
|
||||
|
||||
// ValueOf returns the value of expression e if it is a constant, nil
|
||||
// otherwise.
|
||||
// Precondition: e belongs to the package's ASTs.
|
||||
//
|
||||
func (info *PackageInfo) ValueOf(e ast.Expr) exact.Value {
|
||||
return info.constants[e]
|
||||
|
@ -132,6 +132,7 @@ var testdataTests = []string{
|
||||
"coverage.go",
|
||||
"mrvchain.go",
|
||||
"boundmeth.go",
|
||||
"ifaceprom.go",
|
||||
}
|
||||
|
||||
func run(t *testing.T, dir, input string) bool {
|
||||
|
35
ssa/interp/testdata/ifaceprom.go
vendored
Normal file
35
ssa/interp/testdata/ifaceprom.go
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
// Test of promotion of methods of an interface embedded within a
|
||||
// struct. In particular, this test excercises that the correct
|
||||
// method is called.
|
||||
|
||||
type I interface {
|
||||
one() int
|
||||
two() string
|
||||
}
|
||||
|
||||
type S struct {
|
||||
I
|
||||
}
|
||||
|
||||
type impl struct{}
|
||||
|
||||
func (impl) one() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (impl) two() string {
|
||||
return "two"
|
||||
}
|
||||
|
||||
func main() {
|
||||
var s S
|
||||
s.I = impl{}
|
||||
if one := s.one(); one != 1 {
|
||||
panic(one)
|
||||
}
|
||||
if two := s.two(); two != "two" {
|
||||
panic(two)
|
||||
}
|
||||
}
|
@ -314,11 +314,15 @@ func makeBridgeMethod(prog *Program, typ types.Type, cand *candidate) *Function
|
||||
c.Call.Func = cand.concrete
|
||||
c.Call.Args = append(c.Call.Args, v)
|
||||
} else {
|
||||
c.Call.Method = -1
|
||||
iface := v.Type().Underlying().(*types.Interface)
|
||||
for i, n := 0, iface.NumMethods(); i < n; i++ {
|
||||
if iface.Method(i) == cand.method {
|
||||
c.Call.Method = i
|
||||
break
|
||||
}
|
||||
}
|
||||
c.Call.Recv = v
|
||||
// TODO(adonovan): fix: this looks wrong! Need to
|
||||
// find method index within
|
||||
// v.Type().Underlying().(*types.Interface).Methods()
|
||||
c.Call.Method = 0
|
||||
}
|
||||
for _, arg := range fn.Params[1:] {
|
||||
c.Call.Args = append(c.Call.Args, arg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user