aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2022-09-12 15:51:32 -0700
committerCherry Mui <cherryyz@google.com>2022-09-21 20:25:59 +0000
commite40a130cc02cca954ff8e33aa9f5950ecab99e3b (patch)
tree678954316c813c3921b654e854034d208bfd322a
parente0a364b061060aa0e0ed14df5cdce284e878d605 (diff)
downloadgo-e40a130cc02cca954ff8e33aa9f5950ecab99e3b.tar.gz
go-e40a130cc02cca954ff8e33aa9f5950ecab99e3b.zip
[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 <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> Reviewed-on: https://go-review.googlesource.com/c/go/+/431915
-rw-r--r--src/cmd/compile/internal/types2/issues_test.go37
-rw-r--r--src/cmd/compile/internal/types2/signature.go15
-rw-r--r--src/go/types/issues_test.go37
-rw-r--r--src/go/types/signature.go11
4 files changed, 91 insertions, 9 deletions
diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go
index 697a73525cd..fc4aeb16345 100644
--- a/src/cmd/compile/internal/types2/issues_test.go
+++ b/src/cmd/compile/internal/types2/issues_test.go
@@ -637,3 +637,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})))
+ }
+}
diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go
index c98024f9248..f52f3e25b23 100644
--- a/src/cmd/compile/internal/types2/signature.go
+++ b/src/cmd/compile/internal/types2/signature.go
@@ -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}
diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go
index bd98f481778..2892aab38e3 100644
--- a/src/go/types/issues_test.go
+++ b/src/go/types/issues_test.go
@@ -664,3 +664,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})))
+ }
+}
diff --git a/src/go/types/signature.go b/src/go/types/signature.go
index a340ac701ea..d22646d7a87 100644
--- a/src/go/types/signature.go
+++ b/src/go/types/signature.go
@@ -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}