]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: remove most remaining references to coreType in builtin.go
authorRobert Griesemer <gri@golang.org>
Wed, 26 Feb 2025 23:14:30 +0000 (15:14 -0800)
committerGopher Robot <gobot@golang.org>
Mon, 3 Mar 2025 19:26:31 +0000 (11:26 -0800)
For now, use commonUnder (formerly called sharedUnder) and update
error messages and comments. We can provide better error messages
in individual cases eventually.

Kepp using coreType for make built-in for now because it must accept
different channel types with non-conflicting directions and identical
element types. Added extra test cases.

While at it, rename sharedUnder, sharedUnderOrChan to commonUnder
and commonUnderOrChan, respectively (per suggestion from rfindley).

For #70128.

Change-Id: I11f3d5ce858746574f4302271d8cb763c2cdcf98
Reviewed-on: https://go-review.googlesource.com/c/go/+/653139
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/stmt.go
src/cmd/compile/internal/types2/under.go
src/go/types/builtins.go
src/go/types/call.go
src/go/types/lookup.go
src/go/types/stmt.go
src/go/types/under.go
src/internal/types/testdata/check/builtins1.go

index e7d5f56c81e4de24ef26a05847d2ec348eb18bcf..7160efec896f0045d7a29e6f4f971dba786aa09a 100644 (file)
@@ -377,7 +377,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
        case _Copy:
                // copy(x, y []T) int
-               dst, _ := coreType(x.typ).(*Slice)
+               dst, _ := commonUnder(check, x.typ, nil).(*Slice)
 
                y := args[1]
                src0 := coreString(y.typ)
@@ -520,7 +520,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                case *Map, *Chan:
                        min = 1
                case nil:
-                       check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: no core type", arg0)
+                       check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: no common underlying type", arg0)
                        return
                default:
                        check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)
@@ -818,7 +818,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // unsafe.Slice(ptr *T, len IntegerType) []T
                check.verifyVersionf(call.Fun, go1_17, "unsafe.Slice")
 
-               ptr, _ := coreType(x.typ).(*Pointer)
+               ptr, _ := commonUnder(check, x.typ, nil).(*Pointer)
                if ptr == nil {
                        check.errorf(x, InvalidUnsafeSlice, invalidArg+"%s is not a pointer", x)
                        return
@@ -839,7 +839,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // unsafe.SliceData(slice []T) *T
                check.verifyVersionf(call.Fun, go1_20, "unsafe.SliceData")
 
-               slice, _ := coreType(x.typ).(*Slice)
+               slice, _ := commonUnder(check, x.typ, nil).(*Slice)
                if slice == nil {
                        check.errorf(x, InvalidUnsafeSliceData, invalidArg+"%s is not a slice", x)
                        return
index 3a73a6c2c3899783e5efc8a1ad94e0b9b25bf245..17291b20637d2c78db192c7596d3a2bf6ec76fc4 100644 (file)
@@ -243,9 +243,9 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
        cgocall := x.mode == cgofunc
 
        // If the operand type is a type parameter, all types in its type set
-       // must have a shared underlying type, which must be a signature.
+       // must have a common underlying type, which must be a signature.
        var cause string
-       sig, _ := sharedUnder(check, x.typ, &cause).(*Signature)
+       sig, _ := commonUnder(check, x.typ, &cause).(*Signature)
        if sig == nil {
                if cause != "" {
                        check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, cause)
index 8f87dc096109304d8d4682d4585a073217e57fd9..8dd01918e3f37320ee10404872eec843d24a0018 100644 (file)
@@ -67,13 +67,13 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, fo
 
        obj, index, indirect = lookupFieldOrMethodImpl(T, addressable, pkg, name, foldCase)
 
-       // If we didn't find anything and if we have a type parameter with a shared underlying
+       // If we didn't find anything and if we have a type parameter with a common underlying
        // type, see if there is a matching field (but not a method, those need to be declared
        // explicitly in the constraint). If the constraint is a named pointer type (see above),
        // we are ok here because only fields are accepted as results.
        const enableTParamFieldLookup = false // see go.dev/issue/51576
        if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
-               if t := sharedUnder(nil, T, nil); t != nil {
+               if t := commonUnder(nil, T, nil); t != nil {
                        obj, index, indirect = lookupFieldOrMethodImpl(t, addressable, pkg, name, foldCase)
                        if _, ok := obj.(*Var); !ok {
                                obj, index, indirect = nil, nil, false // accept fields (variables) only
index 3cd29fbb4cddbcb491a4fe7662cc635f1d924f0c..8e5beed3f6bff9fdd212ac779dd7113224025c0e 100644 (file)
@@ -1002,7 +1002,7 @@ func rangeKeyVal(check *Checker, orig Type, allowVersion func(goVersion) bool) (
        }
 
        var cause1 string
-       rtyp := sharedUnderOrChan(check, orig, &cause1)
+       rtyp := commonUnderOrChan(check, orig, &cause1)
        if rtyp == nil {
                return bad(cause1)
        }
@@ -1041,7 +1041,7 @@ func rangeKeyVal(check *Checker, orig Type, allowVersion func(goVersion) bool) (
                assert(typ.Recv() == nil)
                // check iterator argument type
                var cause2 string
-               cb, _ := sharedUnder(check, typ.Params().At(0).Type(), &cause2).(*Signature)
+               cb, _ := commonUnder(check, typ.Params().At(0).Type(), &cause2).(*Signature)
                switch {
                case cb == nil:
                        if cause2 != "" {
index 911687396b8e7268f0c9784f76b1abd16382c5e0..7dc4f7dd7489c0db2957fd65a2f2cae3530b1fd9 100644 (file)
@@ -40,13 +40,17 @@ func typeset(t Type, yield func(t, u Type) bool) {
        yield(t, under(t))
 }
 
-// If t is not a type parameter, sharedUnder returns the underlying type.
-// If t is a type parameter, sharedUnder returns the single underlying
+// TODO(gri) commonUnder, commonUnderOrChan, and Checker.chanElem (expr.go)
+//           have a lot of similarities. Maybe we can find common ground
+//           between them and distill a better factorization.
+
+// If t is not a type parameter, commonUnder returns the underlying type.
+// If t is a type parameter, commonUnder returns the common underlying
 // type of all types in its type set if it exists.
 // Otherwise the result is nil, and *cause reports the error if a non-nil
 // cause is provided.
 // The check parameter is only used if *cause reports an error; it may be nil.
-func sharedUnder(check *Checker, t Type, cause *string) Type {
+func commonUnder(check *Checker, t Type, cause *string) Type {
        var s, su Type
 
        bad := func(s string) bool {
@@ -72,16 +76,16 @@ func sharedUnder(check *Checker, t Type, cause *string) Type {
        return su
 }
 
-// If t is not a type parameter, sharedUnderOrChan returns the underlying type;
+// If t is not a type parameter, commonUnderOrChan returns the underlying type;
 // if that type is a channel type it must permit receive operations.
-// If t is a type parameter, sharedUnderOrChan returns the single underlying
+// If t is a type parameter, commonUnderOrChan returns the common underlying
 // type of all types in its type set if it exists, or, if the type set contains
 // only channel types permitting receive operations and with identical element
-// types, sharedUnderOrChan returns one of those channel types.
+// types, commonUnderOrChan returns one of those channel types.
 // Otherwise the result is nil, and *cause reports the error if a non-nil cause
 // is provided.
 // The check parameter is only used if *cause reports an error; it may be nil.
-func sharedUnderOrChan(check *Checker, t Type, cause *string) Type {
+func commonUnderOrChan(check *Checker, t Type, cause *string) Type {
        var s, su Type
        var sc *Chan
 
index 786c0d5ea4ef9508cc9f9ebea9be2720db4ffb7f..802afe35deb2133598ffa12cea44f02c110bc923 100644 (file)
@@ -380,7 +380,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Copy:
                // copy(x, y []T) int
-               dst, _ := coreType(x.typ).(*Slice)
+               dst, _ := commonUnder(check, x.typ, nil).(*Slice)
 
                y := args[1]
                src0 := coreString(y.typ)
@@ -523,7 +523,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                case *Map, *Chan:
                        min = 1
                case nil:
-                       check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: no core type", arg0)
+                       check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: no common underlying type", arg0)
                        return
                default:
                        check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)
@@ -821,7 +821,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // unsafe.Slice(ptr *T, len IntegerType) []T
                check.verifyVersionf(call.Fun, go1_17, "unsafe.Slice")
 
-               ptr, _ := coreType(x.typ).(*Pointer)
+               ptr, _ := commonUnder(check, x.typ, nil).(*Pointer)
                if ptr == nil {
                        check.errorf(x, InvalidUnsafeSlice, invalidArg+"%s is not a pointer", x)
                        return
@@ -842,7 +842,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // unsafe.SliceData(slice []T) *T
                check.verifyVersionf(call.Fun, go1_20, "unsafe.SliceData")
 
-               slice, _ := coreType(x.typ).(*Slice)
+               slice, _ := commonUnder(check, x.typ, nil).(*Slice)
                if slice == nil {
                        check.errorf(x, InvalidUnsafeSliceData, invalidArg+"%s is not a slice", x)
                        return
index a839477b8c3f6bad646924b24cc388b7e45b5fd0..b722c3ea264445387ae3ab0f378b37d211ce57ee 100644 (file)
@@ -245,9 +245,9 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
        cgocall := x.mode == cgofunc
 
        // If the operand type is a type parameter, all types in its type set
-       // must have a shared underlying type, which must be a signature.
+       // must have a common underlying type, which must be a signature.
        var cause string
-       sig, _ := sharedUnder(check, x.typ, &cause).(*Signature)
+       sig, _ := commonUnder(check, x.typ, &cause).(*Signature)
        if sig == nil {
                if cause != "" {
                        check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, cause)
index cbf16ae7c80f68283ea0645584c3a86325c99039..3779fa7e283b7aa1ba7f99ec311005052f503a80 100644 (file)
@@ -70,13 +70,13 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, fo
 
        obj, index, indirect = lookupFieldOrMethodImpl(T, addressable, pkg, name, foldCase)
 
-       // If we didn't find anything and if we have a type parameter with a shared underlying
+       // If we didn't find anything and if we have a type parameter with a common underlying
        // type, see if there is a matching field (but not a method, those need to be declared
        // explicitly in the constraint). If the constraint is a named pointer type (see above),
        // we are ok here because only fields are accepted as results.
        const enableTParamFieldLookup = false // see go.dev/issue/51576
        if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
-               if t := sharedUnder(nil, T, nil); t != nil {
+               if t := commonUnder(nil, T, nil); t != nil {
                        obj, index, indirect = lookupFieldOrMethodImpl(t, addressable, pkg, name, foldCase)
                        if _, ok := obj.(*Var); !ok {
                                obj, index, indirect = nil, nil, false // accept fields (variables) only
index 983467e36acef7517104779ca93c8ab7022b1c49..297dc3ba06e36543fb6df1a9ace686035e2246a7 100644 (file)
@@ -1020,7 +1020,7 @@ func rangeKeyVal(check *Checker, orig Type, allowVersion func(goVersion) bool) (
        }
 
        var cause1 string
-       rtyp := sharedUnderOrChan(check, orig, &cause1)
+       rtyp := commonUnderOrChan(check, orig, &cause1)
        if rtyp == nil {
                return bad(cause1)
        }
@@ -1059,7 +1059,7 @@ func rangeKeyVal(check *Checker, orig Type, allowVersion func(goVersion) bool) (
                assert(typ.Recv() == nil)
                // check iterator argument type
                var cause2 string
-               cb, _ := sharedUnder(check, typ.Params().At(0).Type(), &cause2).(*Signature)
+               cb, _ := commonUnder(check, typ.Params().At(0).Type(), &cause2).(*Signature)
                switch {
                case cb == nil:
                        if cause2 != "" {
index f72f929039fe0e14274eff9a9b5ddc95729217f4..6dd744c3c221a01fa905d833e7f900eb3f3c9269 100644 (file)
@@ -43,13 +43,17 @@ func typeset(t Type, yield func(t, u Type) bool) {
        yield(t, under(t))
 }
 
-// If t is not a type parameter, sharedUnder returns the underlying type.
-// If t is a type parameter, sharedUnder returns the single underlying
+// TODO(gri) commonUnder, commonUnderOrChan, and Checker.chanElem (expr.go)
+//           have a lot of similarities. Maybe we can find common ground
+//           between them and distill a better factorization.
+
+// If t is not a type parameter, commonUnder returns the underlying type.
+// If t is a type parameter, commonUnder returns the common underlying
 // type of all types in its type set if it exists.
 // Otherwise the result is nil, and *cause reports the error if a non-nil
 // cause is provided.
 // The check parameter is only used if *cause reports an error; it may be nil.
-func sharedUnder(check *Checker, t Type, cause *string) Type {
+func commonUnder(check *Checker, t Type, cause *string) Type {
        var s, su Type
 
        bad := func(s string) bool {
@@ -75,16 +79,16 @@ func sharedUnder(check *Checker, t Type, cause *string) Type {
        return su
 }
 
-// If t is not a type parameter, sharedUnderOrChan returns the underlying type;
+// If t is not a type parameter, commonUnderOrChan returns the underlying type;
 // if that type is a channel type it must permit receive operations.
-// If t is a type parameter, sharedUnderOrChan returns the single underlying
+// If t is a type parameter, commonUnderOrChan returns the common underlying
 // type of all types in its type set if it exists, or, if the type set contains
 // only channel types permitting receive operations and with identical element
-// types, sharedUnderOrChan returns one of those channel types.
+// types, commonUnderOrChan returns one of those channel types.
 // Otherwise the result is nil, and *cause reports the error if a non-nil cause
 // is provided.
 // The check parameter is only used if *cause reports an error; it may be nil.
-func sharedUnderOrChan(check *Checker, t Type, cause *string) Type {
+func commonUnderOrChan(check *Checker, t Type, cause *string) Type {
        var s, su Type
        var sc *Chan
 
index f7ac72d4b9ae60b89e9c478997e74757b13065d6..498dd4b463c3e885231f8801e7b00535441772a7 100644 (file)
@@ -152,7 +152,9 @@ func _[
 
        C1 ~chan int,
        C2 ~chan int | ~chan string,
-       C3 chan int | myChan, // single underlying type
+       C3 chan int | myChan,     // single underlying type
+       C4 chan int | chan<- int, // channels may have different (non-conflicting) directions
+       C5 <-chan int | chan<- int,
 ]() {
        type S0 []int
        _ = make([]int, 10)
@@ -162,7 +164,7 @@ func _[
        _ = make /* ERROR "expects 2 or 3 arguments" */ (S1)
        _ = make(S1, 10, 20)
        _ = make /* ERROR "expects 2 or 3 arguments" */ (S1, 10, 20, 30)
-       _ = make(S2 /* ERROR "cannot make S2: no core type" */ , 10)
+       _ = make(S2 /* ERROR "cannot make S2: no common underlying type" */ , 10)
 
        type M0 map[string]int
        _ = make(map[string]int)
@@ -170,7 +172,7 @@ func _[
        _ = make(M1)
        _ = make(M1, 10)
        _ = make/* ERROR "expects 1 or 2 arguments" */(M1, 10, 20)
-       _ = make(M2 /* ERROR "cannot make M2: no core type" */ )
+       _ = make(M2 /* ERROR "cannot make M2: no common underlying type" */ )
 
        type C0 chan int
        _ = make(chan int)
@@ -178,8 +180,10 @@ func _[
        _ = make(C1)
        _ = make(C1, 10)
        _ = make/* ERROR "expects 1 or 2 arguments" */(C1, 10, 20)
-       _ = make(C2 /* ERROR "cannot make C2: no core type" */ )
+       _ = make(C2 /* ERROR "cannot make C2: no common underlying type" */ )
        _ = make(C3)
+       _ = make(C4)
+       _ = make(C5 /* ERROR "cannot make C5: no common underlying type" */ )
 }
 
 // max