mirror of
https://github.com/golang/go
synced 2024-10-06 08:00:07 +00:00
go/types, types2: allow (string...) signature with NewSignatureType
Includes cases where the core type of the variadic parameter is a slice or bytestring. Permits a client to create the signature for various instantiations of append. Fixes #55030. Change-Id: I0f4983eb00c088cbe1d87954ee0b2df0ccc3bc49 Reviewed-on: https://go-review.googlesource.com/c/go/+/430455 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
706d84fca2
commit
0a1118b8a1
|
@ -636,3 +636,40 @@ func TestIssue50646(t *testing.T) {
|
|||
t.Errorf("comparable not assignable to any")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue55030(t *testing.T) {
|
||||
// makeSig makes the signature func(typ...)
|
||||
makeSig := func(typ Type) {
|
||||
par := NewVar(nopos, nil, "", typ)
|
||||
params := NewTuple(par)
|
||||
NewSignatureType(nil, nil, nil, params, nil, true)
|
||||
}
|
||||
|
||||
// makeSig must not panic for the following (example) types:
|
||||
// []int
|
||||
makeSig(NewSlice(Typ[Int]))
|
||||
|
||||
// string
|
||||
makeSig(Typ[String])
|
||||
|
||||
// P where P's core type is string
|
||||
{
|
||||
P := NewTypeName(nopos, nil, "P", nil) // [P string]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
|
||||
}
|
||||
|
||||
// P where P's core type is an (unnamed) slice
|
||||
{
|
||||
P := NewTypeName(nopos, nil, "P", nil) // [P []int]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
|
||||
}
|
||||
|
||||
// P where P's core type is bytestring (i.e., string or []byte)
|
||||
{
|
||||
t1 := NewTerm(true, Typ[String]) // ~string
|
||||
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
|
||||
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
|
||||
P := NewTypeName(nopos, nil, "P", nil) // [P ~string | []byte]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
package types2
|
||||
|
||||
import "cmd/compile/internal/syntax"
|
||||
import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// API
|
||||
|
@ -28,16 +31,18 @@ type Signature struct {
|
|||
// NewSignatureType creates a new function type for the given receiver,
|
||||
// receiver type parameters, type parameters, parameters, and results. If
|
||||
// variadic is set, params must hold at least one parameter and the last
|
||||
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
|
||||
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
|
||||
// parameter's core type must be of unnamed slice or bytestring type.
|
||||
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
|
||||
// non-empty, recv must be non-nil.
|
||||
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
|
||||
if variadic {
|
||||
n := params.Len()
|
||||
if n == 0 {
|
||||
panic("variadic function must have at least one parameter")
|
||||
}
|
||||
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
|
||||
panic("variadic parameter must be of unnamed slice type")
|
||||
core := coreString(params.At(n - 1).typ)
|
||||
if _, ok := core.(*Slice); !ok && !isString(core) {
|
||||
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
|
||||
}
|
||||
}
|
||||
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
|
||||
|
|
|
@ -663,3 +663,40 @@ func TestIssue50646(t *testing.T) {
|
|||
t.Errorf("comparable not assignable to any")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue55030(t *testing.T) {
|
||||
// makeSig makes the signature func(typ...)
|
||||
makeSig := func(typ Type) {
|
||||
par := NewVar(token.NoPos, nil, "", typ)
|
||||
params := NewTuple(par)
|
||||
NewSignatureType(nil, nil, nil, params, nil, true)
|
||||
}
|
||||
|
||||
// makeSig must not panic for the following (example) types:
|
||||
// []int
|
||||
makeSig(NewSlice(Typ[Int]))
|
||||
|
||||
// string
|
||||
makeSig(Typ[String])
|
||||
|
||||
// P where P's core type is string
|
||||
{
|
||||
P := NewTypeName(token.NoPos, nil, "P", nil) // [P string]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
|
||||
}
|
||||
|
||||
// P where P's core type is an (unnamed) slice
|
||||
{
|
||||
P := NewTypeName(token.NoPos, nil, "P", nil) // [P []int]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
|
||||
}
|
||||
|
||||
// P where P's core type is bytestring (i.e., string or []byte)
|
||||
{
|
||||
t1 := NewTerm(true, Typ[String]) // ~string
|
||||
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
|
||||
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
|
||||
P := NewTypeName(token.NoPos, nil, "P", nil) // [P ~string | []byte]
|
||||
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
@ -41,16 +42,18 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
|
|||
// NewSignatureType creates a new function type for the given receiver,
|
||||
// receiver type parameters, type parameters, parameters, and results. If
|
||||
// variadic is set, params must hold at least one parameter and the last
|
||||
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
|
||||
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
|
||||
// parameter's core type must be of unnamed slice or bytestring type.
|
||||
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
|
||||
// non-empty, recv must be non-nil.
|
||||
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
|
||||
if variadic {
|
||||
n := params.Len()
|
||||
if n == 0 {
|
||||
panic("variadic function must have at least one parameter")
|
||||
}
|
||||
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
|
||||
panic("variadic parameter must be of unnamed slice type")
|
||||
core := coreString(params.At(n - 1).typ)
|
||||
if _, ok := core.(*Slice); !ok && !isString(core) {
|
||||
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
|
||||
}
|
||||
}
|
||||
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
|
||||
|
|
Loading…
Reference in a new issue