Skip to content

Commit e40a130

Browse files
griesemercherrymui
authored andcommitted
[release-branch.go1.18] 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 #55148. Change-Id: I0f4983eb00c088cbe1d87954ee0b2df0ccc3bc49 Reviewed-on: https://go-review.googlesource.com/c/go/+/430455 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/431915
1 parent e0a364b commit e40a130

File tree

4 files changed

+91
-9
lines changed

4 files changed

+91
-9
lines changed

src/cmd/compile/internal/types2/issues_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -637,3 +637,40 @@ func TestIssue50646(t *testing.T) {
637637
t.Errorf("comparable not assignable to any")
638638
}
639639
}
640+
641+
func TestIssue55030(t *testing.T) {
642+
// makeSig makes the signature func(typ...)
643+
makeSig := func(typ Type) {
644+
par := NewVar(nopos, nil, "", typ)
645+
params := NewTuple(par)
646+
NewSignatureType(nil, nil, nil, params, nil, true)
647+
}
648+
649+
// makeSig must not panic for the following (example) types:
650+
// []int
651+
makeSig(NewSlice(Typ[Int]))
652+
653+
// string
654+
makeSig(Typ[String])
655+
656+
// P where P's core type is string
657+
{
658+
P := NewTypeName(nopos, nil, "P", nil) // [P string]
659+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
660+
}
661+
662+
// P where P's core type is an (unnamed) slice
663+
{
664+
P := NewTypeName(nopos, nil, "P", nil) // [P []int]
665+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
666+
}
667+
668+
// P where P's core type is bytestring (i.e., string or []byte)
669+
{
670+
t1 := NewTerm(true, Typ[String]) // ~string
671+
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
672+
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
673+
P := NewTypeName(nopos, nil, "P", nil) // [P ~string | []byte]
674+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
675+
}
676+
}

src/cmd/compile/internal/types2/signature.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package types2
66

7-
import "cmd/compile/internal/syntax"
7+
import (
8+
"cmd/compile/internal/syntax"
9+
"fmt"
10+
)
811

912
// ----------------------------------------------------------------------------
1013
// API
@@ -28,16 +31,18 @@ type Signature struct {
2831
// NewSignatureType creates a new function type for the given receiver,
2932
// receiver type parameters, type parameters, parameters, and results. If
3033
// variadic is set, params must hold at least one parameter and the last
31-
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
32-
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
34+
// parameter's core type must be of unnamed slice or bytestring type.
35+
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
36+
// non-empty, recv must be non-nil.
3337
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
3438
if variadic {
3539
n := params.Len()
3640
if n == 0 {
3741
panic("variadic function must have at least one parameter")
3842
}
39-
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
40-
panic("variadic parameter must be of unnamed slice type")
43+
core := coreString(params.At(n - 1).typ)
44+
if _, ok := core.(*Slice); !ok && !isString(core) {
45+
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
4146
}
4247
}
4348
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}

src/go/types/issues_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -664,3 +664,40 @@ func TestIssue50646(t *testing.T) {
664664
t.Errorf("comparable not assignable to any")
665665
}
666666
}
667+
668+
func TestIssue55030(t *testing.T) {
669+
// makeSig makes the signature func(typ...)
670+
makeSig := func(typ Type) {
671+
par := NewVar(token.NoPos, nil, "", typ)
672+
params := NewTuple(par)
673+
NewSignatureType(nil, nil, nil, params, nil, true)
674+
}
675+
676+
// makeSig must not panic for the following (example) types:
677+
// []int
678+
makeSig(NewSlice(Typ[Int]))
679+
680+
// string
681+
makeSig(Typ[String])
682+
683+
// P where P's core type is string
684+
{
685+
P := NewTypeName(token.NoPos, nil, "P", nil) // [P string]
686+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
687+
}
688+
689+
// P where P's core type is an (unnamed) slice
690+
{
691+
P := NewTypeName(token.NoPos, nil, "P", nil) // [P []int]
692+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
693+
}
694+
695+
// P where P's core type is bytestring (i.e., string or []byte)
696+
{
697+
t1 := NewTerm(true, Typ[String]) // ~string
698+
t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte
699+
u := NewUnion([]*Term{t1, t2}) // ~string | []byte
700+
P := NewTypeName(token.NoPos, nil, "P", nil) // [P ~string | []byte]
701+
makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})))
702+
}
703+
}

src/go/types/signature.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package types
66

77
import (
8+
"fmt"
89
"go/ast"
910
"go/token"
1011
)
@@ -41,16 +42,18 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
4142
// NewSignatureType creates a new function type for the given receiver,
4243
// receiver type parameters, type parameters, parameters, and results. If
4344
// variadic is set, params must hold at least one parameter and the last
44-
// parameter must be of unnamed slice type. If recv is non-nil, typeParams must
45-
// be empty. If recvTypeParams is non-empty, recv must be non-nil.
45+
// parameter's core type must be of unnamed slice or bytestring type.
46+
// If recv is non-nil, typeParams must be empty. If recvTypeParams is
47+
// non-empty, recv must be non-nil.
4648
func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
4749
if variadic {
4850
n := params.Len()
4951
if n == 0 {
5052
panic("variadic function must have at least one parameter")
5153
}
52-
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
53-
panic("variadic parameter must be of unnamed slice type")
54+
core := coreString(params.At(n - 1).typ)
55+
if _, ok := core.(*Slice); !ok && !isString(core) {
56+
panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
5457
}
5558
}
5659
sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}

0 commit comments

Comments
 (0)