1
0
mirror of https://github.com/golang/go synced 2024-11-25 10:17:57 -07:00

go/types, types2: adjust Checker.unpackRecv signature slightly

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>
This commit is contained in:
Robert Griesemer 2024-06-26 15:20:41 -07:00 committed by Gopher Robot
parent f234c9423b
commit 1d542efe23
4 changed files with 46 additions and 40 deletions

View 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
}

View 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.

View 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
}

View 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.