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:
parent
f234c9423b
commit
1d542efe23
@ -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
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user