]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: adjust Checker.unpackRecv signature slightly
authorRobert Griesemer <gri@golang.org>
Wed, 26 Jun 2024 22:20:41 +0000 (15:20 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 26 Jul 2024 20:13:11 +0000 (20:13 +0000)
Instead of returning the receiver type name (rname), return the
receiver type base expression (base), with pointer indirections
stripped. The type base may or may not not be a type name. This
is needed for further rewrites of the signature type-checking code.
Adjust call sites accordingly to preserve existing behavior.

For #51343.

Change-Id: Ib472ca25d43ec340762d0a8dd1ad038568c2b2bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/595335
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/resolver.go
src/cmd/compile/internal/types2/signature.go
src/go/types/resolver.go
src/go/types/signature.go

index 4d9b4f92e1d86e7dbd82a9a40d2825af2e35b17a..c47672fa1ea397548d82309d533afee7c26b2d6c 100644 (file)
@@ -445,11 +445,11 @@ func (check *Checker) collectObjects() {
                                } else {
                                        // method
                                        // d.Recv != nil
-                                       ptr, recv, _ := check.unpackRecv(s.Recv.Type, false)
+                                       ptr, base, _ := check.unpackRecv(s.Recv.Type, false)
                                        // Methods with invalid receiver cannot be associated to a type, and
                                        // methods with blank _ names are never found; no need to collect any
                                        // of them. They will still be type-checked with all the other functions.
-                                       if recv != nil && name != "_" {
+                                       if recv, _ := base.(*syntax.Name); recv != nil && name != "_" {
                                                methods = append(methods, methodInfo{obj, ptr, recv})
                                        }
                                        check.recordDef(s.Name, obj)
@@ -506,37 +506,43 @@ func (check *Checker) collectObjects() {
        }
 }
 
-// unpackRecv unpacks a receiver type and returns its components: ptr indicates whether
-// rtyp is a pointer receiver, rname is the receiver type name, and tparams are its
-// type parameters, if any. The type parameters are only unpacked if unpackParams is
-// set. If rname is nil, the receiver is unusable (i.e., the source has a bug which we
-// cannot easily work around).
-func (check *Checker) unpackRecv(rtyp syntax.Expr, unpackParams bool) (ptr bool, rname *syntax.Name, tparams []*syntax.Name) {
-L: // unpack receiver type
+// unpackRecv unpacks a receiver type expression and returns its components: ptr indicates
+// whether rtyp is a pointer receiver, base is the receiver base type expression stripped
+// of its type parameters (if any), and tparams are its type parameter names, if any. The
+// type parameters are only unpacked if unpackParams is set. For instance, given the rtyp
+//
+//     *T[A, _]
+//
+// ptr is true, base is T, and tparams is [A, _] (assuming unpackParams is set).
+// Note that base may not be a *syntax.Name for erroneous programs.
+func (check *Checker) unpackRecv(rtyp syntax.Expr, unpackParams bool) (ptr bool, base syntax.Expr, tparams []*syntax.Name) {
+       // unpack receiver type
        // This accepts invalid receivers such as ***T and does not
        // work for other invalid receivers, but we don't care. The
        // validity of receiver expressions is checked elsewhere.
+       base = rtyp
+L:
        for {
-               switch t := rtyp.(type) {
+               switch t := base.(type) {
                case *syntax.ParenExpr:
-                       rtyp = t.X
+                       base = t.X
                // case *ast.StarExpr:
                //      ptr = true
-               //      rtyp = t.X
+               //      base = t.X
                case *syntax.Operation:
                        if t.Op != syntax.Mul || t.Y != nil {
                                break
                        }
                        ptr = true
-                       rtyp = t.X
+                       base = t.X
                default:
                        break L
                }
        }
 
        // unpack type parameters, if any
-       if ptyp, _ := rtyp.(*syntax.IndexExpr); ptyp != nil {
-               rtyp = ptyp.X
+       if ptyp, _ := base.(*syntax.IndexExpr); ptyp != nil {
+               base = ptyp.X
                if unpackParams {
                        for _, arg := range syntax.UnpackListExpr(ptyp.Index) {
                                var par *syntax.Name
@@ -559,9 +565,6 @@ L: // unpack receiver type
                }
        }
 
-       // unpack receiver name
-       rname, _ = rtyp.(*syntax.Name)
-
        return
 }
 
index ed4ca1f08df6d987770f6d3aebe37be69aae1435..5dacd8fa1a32e523b91c28585aaeeb8aae6ce8b0 100644 (file)
@@ -103,7 +103,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                // collect generic receiver type parameters, if any
                // - a receiver type parameter is like any other type parameter, except that it is declared implicitly
                // - the receiver specification acts as local declaration for its type parameters, which may be blank
-               _, rname, rparams := check.unpackRecv(recvPar.Type, true)
+               _, base, rparams := check.unpackRecv(recvPar.Type, true)
                if len(rparams) > 0 {
                        // The scope of the type parameter T in "func (r T[T]) f()"
                        // starts after f, not at "r"; see #52038.
@@ -131,7 +131,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                        // determine receiver type to get its type parameters
                        // and the respective type parameter bounds
                        var recvTParams []*TypeParam
-                       if rname != nil {
+                       if rname := base.(*syntax.Name); rname != nil {
                                // recv should be a Named type (otherwise an error is reported elsewhere)
                                // Also: Don't report an error via genericType since it will be reported
                                //       again when we type-check the signature.
index 041c4536672fe5f3227b6e5476e4bd205d9f7454..5d6bf7aedac857c8f51399dd746d63d814739236 100644 (file)
@@ -437,11 +437,11 @@ func (check *Checker) collectObjects() {
                                        //                when type checking the function type. Confirm that
                                        //                we don't need to check tparams here.
 
-                                       ptr, recv, _ := check.unpackRecv(d.decl.Recv.List[0].Type, false)
+                                       ptr, base, _ := check.unpackRecv(d.decl.Recv.List[0].Type, false)
                                        // (Methods with invalid receiver cannot be associated to a type, and
                                        // methods with blank _ names are never found; no need to collect any
                                        // of them. They will still be type-checked with all the other functions.)
-                                       if recv != nil && name != "_" {
+                                       if recv, _ := base.(*ast.Ident); recv != nil && name != "_" {
                                                methods = append(methods, methodInfo{obj, ptr, recv})
                                        }
                                        check.recordDef(d.decl.Name, obj)
@@ -496,33 +496,39 @@ func (check *Checker) collectObjects() {
        }
 }
 
-// unpackRecv unpacks a receiver type and returns its components: ptr indicates whether
-// rtyp is a pointer receiver, rname is the receiver type name, and tparams are its
-// type parameters, if any. The type parameters are only unpacked if unpackParams is
-// set. If rname is nil, the receiver is unusable (i.e., the source has a bug which we
-// cannot easily work around).
-func (check *Checker) unpackRecv(rtyp ast.Expr, unpackParams bool) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) {
-L: // unpack receiver type
+// unpackRecv unpacks a receiver type expression and returns its components: ptr indicates
+// whether rtyp is a pointer receiver, base is the receiver base type expression stripped
+// of its type parameters (if any), and tparams are its type parameter names, if any. The
+// type parameters are only unpacked if unpackParams is set. For instance, given the rtyp
+//
+//     *T[A, _]
+//
+// ptr is true, base is T, and tparams is [A, _] (assuming unpackParams is set).
+// Note that base may not be a *ast.Ident for erroneous programs.
+func (check *Checker) unpackRecv(rtyp ast.Expr, unpackParams bool) (ptr bool, base ast.Expr, tparams []*ast.Ident) {
+       // unpack receiver type
        // This accepts invalid receivers such as ***T and does not
        // work for other invalid receivers, but we don't care. The
        // validity of receiver expressions is checked elsewhere.
+       base = rtyp
+L:
        for {
-               switch t := rtyp.(type) {
+               switch t := base.(type) {
                case *ast.ParenExpr:
-                       rtyp = t.X
+                       base = t.X
                case *ast.StarExpr:
                        ptr = true
-                       rtyp = t.X
+                       base = t.X
                default:
                        break L
                }
        }
 
        // unpack type parameters, if any
-       switch rtyp.(type) {
+       switch base.(type) {
        case *ast.IndexExpr, *ast.IndexListExpr:
-               ix := typeparams.UnpackIndexExpr(rtyp)
-               rtyp = ix.X
+               ix := typeparams.UnpackIndexExpr(base)
+               base = ix.X
                if unpackParams {
                        for _, arg := range ix.Indices {
                                var par *ast.Ident
@@ -544,9 +550,6 @@ L: // unpack receiver type
                }
        }
 
-       // unpack receiver name
-       rname, _ = rtyp.(*ast.Ident)
-
        return
 }
 
index 651a333e24f8bd0a2560ef75afec9a0c0e0b2d2f..bcac0da012824c997e481973163e4a74c188d5d9 100644 (file)
@@ -114,7 +114,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                // collect generic receiver type parameters, if any
                // - a receiver type parameter is like any other type parameter, except that it is declared implicitly
                // - the receiver specification acts as local declaration for its type parameters, which may be blank
-               _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
+               _, base, rparams := check.unpackRecv(recvPar.List[0].Type, true)
                if len(rparams) > 0 {
                        // The scope of the type parameter T in "func (r T[T]) f()"
                        // starts after f, not at "r"; see #52038.
@@ -139,7 +139,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                        // determine receiver type to get its type parameters
                        // and the respective type parameter bounds
                        var recvTParams []*TypeParam
-                       if rname != nil {
+                       if rname := base.(*ast.Ident); rname != nil {
                                // recv should be a Named type (otherwise an error is reported elsewhere)
                                // Also: Don't report an error via genericType since it will be reported
                                //       again when we type-check the signature.