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
This commit is contained in:
parent
345b6437fc
commit
87301fe3a6
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue