diff --git a/go/ssa/interp/ops.go b/go/ssa/interp/ops.go index 86aaee0e..b1fca002 100644 --- a/go/ssa/interp/ops.go +++ b/go/ssa/interp/ops.go @@ -952,11 +952,13 @@ func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value // append([]T, ...[]T) []T return append(args[0].([]value), args[1].([]value)...) - case "copy": // copy([]T, []T) int - if _, ok := args[1].(string); ok { - panic("copy([]byte, string) not yet implemented") + case "copy": // copy([]T, []T) int or copy([]byte, string) int + src := args[1] + if _, ok := src.(string); ok { + params := fn.Type().(*types.Signature).Params() + src = conv(params.At(0).Type(), params.At(1).Type(), src) } - return copy(args[0].([]value), args[1].([]value)) + return copy(args[0].([]value), src.([]value)) case "close": // close(chan T) close(args[0].(chan value)) diff --git a/go/types/builtins.go b/go/types/builtins.go index aca43225..cc048e3a 100644 --- a/go/types/builtins.go +++ b/go/types/builtins.go @@ -302,12 +302,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ)) + } x.mode = value x.typ = Typ[Int] - if check.Types != nil { - S := NewSlice(dst) - check.recordBuiltinType(call.Fun, makeSig(x.typ, S, S)) - } case _Delete: // delete(m, k) diff --git a/go/types/builtins_test.go b/go/types/builtins_test.go index ca3bac88..8afcb6ba 100644 --- a/go/types/builtins_test.go +++ b/go/types/builtins_test.go @@ -50,7 +50,10 @@ var builtinCalls = []struct { {"complex", `type F64 float64; var re, im F64; _ = complex(re, im)`, `func(p.F64, p.F64) complex128`}, {"copy", `var src, dst []byte; copy(dst, src)`, `func([]byte, []byte) int`}, - {"copy", `type T [][]int; var src, dst T; _ = copy(dst, src)`, `func([][]int, [][]int) int`}, + {"copy", `type T [][]int; var src, dst T; _ = copy(dst, src)`, `func(p.T, p.T) int`}, + {"copy", `var src string; var dst []byte; copy(dst, src)`, `func([]byte, string) int`}, + {"copy", `type T string; type U []byte; var src T; var dst U; copy(dst, src)`, `func(p.U, p.T) int`}, + {"copy", `var dst []byte; copy(dst, "hello")`, `func([]byte, string) int`}, {"delete", `var m map[string]bool; delete(m, "foo")`, `func(map[string]bool, string)`}, {"delete", `type (K string; V int); var m map[K]V; delete(m, "foo")`, `func(map[p.K]p.V, p.K)`},