]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: remove need for coreString in signature.go
authorRobert Griesemer <gri@golang.org>
Fri, 7 Mar 2025 00:06:55 +0000 (16:06 -0800)
committerGopher Robot <gobot@golang.org>
Tue, 11 Mar 2025 12:44:12 +0000 (05:44 -0700)
Also, add additional test cases for NewSignatureType
to check expected panic behavior.

Change-Id: If26cd81a2af384bf2084dd09119483c0584715c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/655695
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
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 51014d8d8248d3ed95d7eebcec2d4d9ba88ff80e..8ddb39987a5db05fc13a9396120115e26bf00974 100644 (file)
@@ -627,7 +627,15 @@ func TestIssue50646(t *testing.T) {
 
 func TestIssue55030(t *testing.T) {
        // makeSig makes the signature func(typ...)
-       makeSig := func(typ Type) {
+       // If valid is not set, making that signature is expected to panic.
+       makeSig := func(typ Type, valid bool) {
+               if !valid {
+                       defer func() {
+                               if recover() == nil {
+                                       panic("NewSignatureType panic expected")
+                               }
+                       }()
+               }
                par := NewParam(nopos, nil, "", typ)
                params := NewTuple(par)
                NewSignatureType(nil, nil, nil, params, nil, true)
@@ -635,30 +643,46 @@ func TestIssue55030(t *testing.T) {
 
        // makeSig must not panic for the following (example) types:
        // []int
-       makeSig(NewSlice(Typ[Int]))
+       makeSig(NewSlice(Typ[Int]), true)
 
        // string
-       makeSig(Typ[String])
+       makeSig(Typ[String], true)
 
-       // P where P's core type is string
+       // P where P's common underlying type is string
        {
                P := NewTypeName(nopos, nil, "P", nil) // [P string]
-               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})), true)
        }
 
-       // P where P's core type is an (unnamed) slice
+       // P where P's common underlying type is an (unnamed) slice
        {
                P := NewTypeName(nopos, nil, "P", nil) // [P []int]
-               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})), true)
        }
 
-       // P where P's core type is bytestring (i.e., string or []byte)
+       // P where P's type set contains strings and []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})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})), true)
+       }
+
+       // makeSig must panic for the following (example) types:
+       // int
+       makeSig(Typ[Int], false)
+
+       // P where P's type set doesn't have any specific types
+       {
+               P := NewTypeName(nopos, nil, "P", nil) // [P any]
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Universe.Lookup("any").Type()})), false)
+       }
+
+       // P where P's type set doesn't have any slice or string types
+       {
+               P := NewTypeName(nopos, nil, "P", nil) // [P any]
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[Int]})), false)
        }
 }
 
index 505997110b8ffe28af0808502b104b7649c90b22..eaecb77af52db15b3018b5876c070ea1ffb08bd1 100644 (file)
@@ -32,9 +32,13 @@ 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's core type must be of unnamed slice or bytestring type.
+// 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 an unnamed slice or a type parameter whose
+// type set has an unnamed slice as common underlying type.
+// As a special case, for variadic signatures the last parameter may
+// also be a string type, or a type parameter containing a mix of byte
+// slices and string types in its type set.
 // 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 {
@@ -43,9 +47,25 @@ func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params
                if n == 0 {
                        panic("variadic function must have at least one parameter")
                }
-               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 common underlying type", core.String()))
+               last := params.At(n - 1).typ
+               var S *Slice
+               typeset(last, func(t, _ Type) bool {
+                       var s *Slice
+                       if isString(t) {
+                               s = NewSlice(universeByte)
+                       } else {
+                               s, _ = Unalias(t).(*Slice) // don't accept a named slice type
+                       }
+                       if S == nil {
+                               S = s
+                       } else if !Identical(S, s) {
+                               S = nil
+                               return false
+                       }
+                       return true
+               })
+               if S == nil {
+                       panic(fmt.Sprintf("got %s, want variadic parameter of unnamed slice or string type", last))
                }
        }
        sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
index 2c1cfb8bfac561776e86031598b32dd7796425c0..6388dcf6876e75e56b2ab56aa3c9bf14549dfe3b 100644 (file)
@@ -637,7 +637,15 @@ func TestIssue50646(t *testing.T) {
 
 func TestIssue55030(t *testing.T) {
        // makeSig makes the signature func(typ...)
-       makeSig := func(typ Type) {
+       // If valid is not set, making that signature is expected to panic.
+       makeSig := func(typ Type, valid bool) {
+               if !valid {
+                       defer func() {
+                               if recover() == nil {
+                                       panic("NewSignatureType panic expected")
+                               }
+                       }()
+               }
                par := NewParam(nopos, nil, "", typ)
                params := NewTuple(par)
                NewSignatureType(nil, nil, nil, params, nil, true)
@@ -645,30 +653,46 @@ func TestIssue55030(t *testing.T) {
 
        // makeSig must not panic for the following (example) types:
        // []int
-       makeSig(NewSlice(Typ[Int]))
+       makeSig(NewSlice(Typ[Int]), true)
 
        // string
-       makeSig(Typ[String])
+       makeSig(Typ[String], true)
 
-       // P where P's core type is string
+       // P where P's common underlying type is string
        {
                P := NewTypeName(nopos, nil, "P", nil) // [P string]
-               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]})), true)
        }
 
-       // P where P's core type is an (unnamed) slice
+       // P where P's common underlying type is an (unnamed) slice
        {
                P := NewTypeName(nopos, nil, "P", nil) // [P []int]
-               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])})), true)
        }
 
-       // P where P's core type is bytestring (i.e., string or []byte)
+       // P where P's type set contains strings and []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})))
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u})), true)
+       }
+
+       // makeSig must panic for the following (example) types:
+       // int
+       makeSig(Typ[Int], false)
+
+       // P where P's type set doesn't have any specific types
+       {
+               P := NewTypeName(nopos, nil, "P", nil) // [P any]
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Universe.Lookup("any").Type()})), false)
+       }
+
+       // P where P's type set doesn't have any slice or string types
+       {
+               P := NewTypeName(nopos, nil, "P", nil) // [P any]
+               makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[Int]})), false)
        }
 }
 
index 0bf28f8947c9596f1ece1cab928e589b8d95bf5d..f059ecb183a73adc980943f8398ca502e604fddb 100644 (file)
@@ -45,9 +45,13 @@ 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's core type must be of unnamed slice or bytestring type.
+// 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 an unnamed slice or a type parameter whose
+// type set has an unnamed slice as common underlying type.
+// As a special case, for variadic signatures the last parameter may
+// also be a string type, or a type parameter containing a mix of byte
+// slices and string types in its type set.
 // 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 {
@@ -56,9 +60,25 @@ func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params
                if n == 0 {
                        panic("variadic function must have at least one parameter")
                }
-               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 common underlying type", core.String()))
+               last := params.At(n - 1).typ
+               var S *Slice
+               typeset(last, func(t, _ Type) bool {
+                       var s *Slice
+                       if isString(t) {
+                               s = NewSlice(universeByte)
+                       } else {
+                               s, _ = Unalias(t).(*Slice) // don't accept a named slice type
+                       }
+                       if S == nil {
+                               S = s
+                       } else if !Identical(S, s) {
+                               S = nil
+                               return false
+                       }
+                       return true
+               })
+               if S == nil {
+                       panic(fmt.Sprintf("got %s, want variadic parameter of unnamed slice or string type", last))
                }
        }
        sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}