From 87301fe3a66ca581e210c9e5c7b400bf0790bfe9 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 27 Jun 2014 16:00:54 -0700 Subject: [PATCH] go.tools/go/types: type the append([]byte, string...) builtin more correctly This builtin is a little weird in this form as it is (to my knowledge) the only function that takes a variadic argument of non-slice type. The language provides no syntax to express this, so we pick a stringification for such arguments that does not appear in the language. Specifically, use T... instead of ...T to distinguish it from the normal case where the type is a slice. This change lets the go/ssa package produce more efficient IR by avoiding an extra conversion of the second argument. LGTM=gri R=gri CC=adonovan, golang-codereviews https://golang.org/cl/108230044 --- go/types/builtins.go | 2 +- go/types/builtins_test.go | 8 +++----- go/types/typestring.go | 10 ++++++++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/go/types/builtins.go b/go/types/builtins.go index cc048e3a..fcffa652 100644 --- a/go/types/builtins.go +++ b/go/types/builtins.go @@ -100,7 +100,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } if isString(x.typ) { if check.Types != nil { - sig := makeSig(S, S, NewSlice(UniverseByte)) + sig := makeSig(S, S, x.typ) sig.variadic = true check.recordBuiltinType(call.Fun, sig) } diff --git a/go/types/builtins_test.go b/go/types/builtins_test.go index 8afcb6ba..9164cf33 100644 --- a/go/types/builtins_test.go +++ b/go/types/builtins_test.go @@ -21,11 +21,9 @@ var builtinCalls = []struct { {"append", `var s []int; _ = append(s, 0)`, `func([]int, ...int) []int`}, {"append", `var s []int; _ = (append)(s, 0)`, `func([]int, ...int) []int`}, {"append", `var s []byte; _ = ((append))(s, 0)`, `func([]byte, ...byte) []byte`}, - // Note that ...uint8 (instead of ..byte) appears below because that is the type - // that corresponds to Typ[byte] (an alias) - in the other cases, the type name - // is chosen by the source. Either way, byte and uint8 denote identical types. - {"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, ...byte) []byte`}, - {"append", `type T []byte; var s T; _ = append(s, "foo"...)`, `func(p.T, ...byte) p.T`}, + {"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, string...) []byte`}, + {"append", `type T []byte; var s T; var str string; _ = append(s, str...)`, `func(p.T, string...) p.T`}, + {"append", `type T []byte; type U string; var s T; var str U; _ = append(s, str...)`, `func(p.T, p.U...) p.T`}, {"cap", `var s [10]int; _ = cap(s)`, `invalid type`}, // constant {"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant diff --git a/go/types/typestring.go b/go/types/typestring.go index ad6a1d13..0b5e87be 100644 --- a/go/types/typestring.go +++ b/go/types/typestring.go @@ -217,8 +217,14 @@ func writeTuple(buf *bytes.Buffer, this *Package, tup *Tuple, variadic bool, vis } typ := v.typ if variadic && i == len(tup.vars)-1 { - buf.WriteString("...") - typ = typ.(*Slice).elem + if s, ok := typ.(*Slice); ok { + buf.WriteString("...") + typ = s.elem + } else { + writeType(buf, this, typ, visited) + buf.WriteString("...") + continue + } } writeType(buf, this, typ, visited) }