Skip to content

Commit dfdfa49

Browse files
adonovangopherbot
authored andcommitted
go/types/objectpath: support Signature.RecvTypeParams
Fixes golang/go#68055 Change-Id: I57c7641ab40521919053c1cb6492152e08b341c9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/593316 Reviewed-by: Tim King <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 2d104ec commit dfdfa49

File tree

2 files changed

+41
-20
lines changed

2 files changed

+41
-20
lines changed

go/types/objectpath/objectpath.go

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type Path string
5151
//
5252
// PO package->object Package.Scope.Lookup
5353
// OT object->type Object.Type
54-
// TT type->type Type.{Elem,Key,Params,Results,Underlying} [EKPRU]
54+
// TT type->type Type.{Elem,Key,{,{,Recv}Type}Params,Results,Underlying} [EKPRUTrC]
5555
// TO type->object Type.{At,Field,Method,Obj} [AFMO]
5656
//
5757
// All valid paths start with a package and end at an object
@@ -63,8 +63,8 @@ type Path string
6363
// - The only PO operator is Package.Scope.Lookup, which requires an identifier.
6464
// - The only OT operator is Object.Type,
6565
// which we encode as '.' because dot cannot appear in an identifier.
66-
// - The TT operators are encoded as [EKPRUTC];
67-
// one of these (TypeParam) requires an integer operand,
66+
// - The TT operators are encoded as [EKPRUTrC];
67+
// two of these ({,Recv}TypeParams) require an integer operand,
6868
// which is encoded as a string of decimal digits.
6969
// - The TO operators are encoded as [AFMO];
7070
// three of these (At,Field,Method) require an integer operand,
@@ -98,19 +98,20 @@ const (
9898
opType = '.' // .Type() (Object)
9999

100100
// type->type operators
101-
opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map)
102-
opKey = 'K' // .Key() (Map)
103-
opParams = 'P' // .Params() (Signature)
104-
opResults = 'R' // .Results() (Signature)
105-
opUnderlying = 'U' // .Underlying() (Named)
106-
opTypeParam = 'T' // .TypeParams.At(i) (Named, Signature)
107-
opConstraint = 'C' // .Constraint() (TypeParam)
101+
opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map)
102+
opKey = 'K' // .Key() (Map)
103+
opParams = 'P' // .Params() (Signature)
104+
opResults = 'R' // .Results() (Signature)
105+
opUnderlying = 'U' // .Underlying() (Named)
106+
opTypeParam = 'T' // .TypeParams.At(i) (Named, Signature)
107+
opRecvTypeParam = 'r' // .RecvTypeParams.At(i) (Signature)
108+
opConstraint = 'C' // .Constraint() (TypeParam)
108109

109110
// type->object operators
110-
opAt = 'A' // .At(i) (Tuple)
111-
opField = 'F' // .Field(i) (Struct)
112-
opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
113-
opObj = 'O' // .Obj() (Named, TypeParam)
111+
opAt = 'A' // .At(i) (Tuple)
112+
opField = 'F' // .Field(i) (Struct)
113+
opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
114+
opObj = 'O' // .Obj() (Named, TypeParam)
114115
)
115116

116117
// For is equivalent to new(Encoder).For(obj).
@@ -286,7 +287,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
286287
}
287288
} else {
288289
if named, _ := T.(*types.Named); named != nil {
289-
if r := findTypeParam(obj, named.TypeParams(), path, nil); r != nil {
290+
if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam, nil); r != nil {
290291
// generic named type
291292
return Path(r), nil
292293
}
@@ -462,7 +463,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
462463
}
463464
return find(obj, T.Elem(), append(path, opElem), seen)
464465
case *types.Signature:
465-
if r := findTypeParam(obj, T.TypeParams(), path, seen); r != nil {
466+
if r := findTypeParam(obj, T.RecvTypeParams(), path, opRecvTypeParam, nil); r != nil {
467+
return r
468+
}
469+
if r := findTypeParam(obj, T.TypeParams(), path, opTypeParam, seen); r != nil {
466470
return r
467471
}
468472
if r := find(obj, T.Params(), append(path, opParams), seen); r != nil {
@@ -525,10 +529,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
525529
panic(T)
526530
}
527531

528-
func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte {
532+
func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte, seen map[*types.TypeName]bool) []byte {
529533
for i := 0; i < list.Len(); i++ {
530534
tparam := list.At(i)
531-
path2 := appendOpArg(path, opTypeParam, i)
535+
path2 := appendOpArg(path, op, i)
532536
if r := find(obj, tparam, path2, seen); r != nil {
533537
return r
534538
}
@@ -580,10 +584,10 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
580584
code := suffix[0]
581585
suffix = suffix[1:]
582586

583-
// Codes [AFM] have an integer operand.
587+
// Codes [AFMTr] have an integer operand.
584588
var index int
585589
switch code {
586-
case opAt, opField, opMethod, opTypeParam:
590+
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
587591
rest := strings.TrimLeft(suffix, "0123456789")
588592
numerals := suffix[:len(suffix)-len(rest)]
589593
suffix = rest
@@ -664,6 +668,17 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
664668
}
665669
t = tparams.At(index)
666670

671+
case opRecvTypeParam:
672+
sig, ok := t.(*types.Signature) // Signature
673+
if !ok {
674+
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t)
675+
}
676+
rtparams := sig.RecvTypeParams()
677+
if n := rtparams.Len(); index >= n {
678+
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n)
679+
}
680+
t = rtparams.At(index)
681+
667682
case opConstraint:
668683
tparam, ok := t.(*types.TypeParam)
669684
if !ok {
@@ -725,6 +740,10 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
725740
}
726741
}
727742

743+
if obj == nil {
744+
panic(p) // path does not end in an object-valued operator
745+
}
746+
728747
if obj.Pkg() != pkg {
729748
return nil, fmt.Errorf("path denotes %s, which belongs to a different package", obj)
730749
}

go/types/objectpath/objectpath_go118_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ func F[FP0 any, FP1 interface{ M() }](FP0, FP1) {}
3939
{"b", "T", "type b.T[TP0 any, TP1 interface{M0(); M1()}] struct{}", ""},
4040
{"b", "T.O", "type b.T[TP0 any, TP1 interface{M0(); M1()}] struct{}", ""},
4141
{"b", "T.M0", "func (b.T[RP0, RP1]).M()", ""},
42+
{"b", "T.M0.r1O", "type parameter RP1 interface{M0(); M1()}", ""},
43+
{"b", "T.M0.r1CM1", "func (interface).M1()", ""},
4244
{"b", "T.T0O", "type parameter TP0 any", ""},
4345
{"b", "T.T1O", "type parameter TP1 interface{M0(); M1()}", ""},
4446
{"b", "T.T1CM0", "func (interface).M0()", ""},

0 commit comments

Comments
 (0)