]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.19] go/types, types2: allow (string...) signature with NewSignatu...
authorRobert Griesemer <gri@golang.org>
Mon, 12 Sep 2022 22:51:32 +0000 (15:51 -0700)
committerCherry Mui <cherryyz@google.com>
Wed, 21 Sep 2022 20:26:19 +0000 (20:26 +0000)
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 #55149.

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/+/431935

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

index 697a73525cd4a88e069c90ed83320f13c93ae338..fc4aeb163456b002308e905142b58de47e1a254b 100644 (file)
@@ -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})))
+       }
+}
index 1b61b368d2a3fb65fa5069414870b2df6185db85..2e518adc41c87965ff2cd35673c389e29a8ca675 100644 (file)
@@ -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}
index bd98f481778437be635f6de78114198d62fe939b..2892aab38e33d5de104d6afdf84c7721a01b0985 100644 (file)
@@ -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})))
+       }
+}
index 82177a1c58d5a12767cbb2fdfb779f117bd4d6a6..b8ef42b288dc5f1ddee1a1c5100552599a249687 100644 (file)
@@ -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}