@@ -51,7 +51,7 @@ type Path string
51
51
//
52
52
// PO package->object Package.Scope.Lookup
53
53
// 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 ]
55
55
// TO type->object Type.{At,Field,Method,Obj} [AFMO]
56
56
//
57
57
// All valid paths start with a package and end at an object
@@ -63,8 +63,8 @@ type Path string
63
63
// - The only PO operator is Package.Scope.Lookup, which requires an identifier.
64
64
// - The only OT operator is Object.Type,
65
65
// 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,
68
68
// which is encoded as a string of decimal digits.
69
69
// - The TO operators are encoded as [AFMO];
70
70
// three of these (At,Field,Method) require an integer operand,
@@ -98,19 +98,20 @@ const (
98
98
opType = '.' // .Type() (Object)
99
99
100
100
// 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)
108
109
109
110
// 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)
114
115
)
115
116
116
117
// For is equivalent to new(Encoder).For(obj).
@@ -286,7 +287,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
286
287
}
287
288
} else {
288
289
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 {
290
291
// generic named type
291
292
return Path (r ), nil
292
293
}
@@ -462,7 +463,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
462
463
}
463
464
return find (obj , T .Elem (), append (path , opElem ), seen )
464
465
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 {
466
470
return r
467
471
}
468
472
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]
525
529
panic (T )
526
530
}
527
531
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 {
529
533
for i := 0 ; i < list .Len (); i ++ {
530
534
tparam := list .At (i )
531
- path2 := appendOpArg (path , opTypeParam , i )
535
+ path2 := appendOpArg (path , op , i )
532
536
if r := find (obj , tparam , path2 , seen ); r != nil {
533
537
return r
534
538
}
@@ -580,10 +584,10 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
580
584
code := suffix [0 ]
581
585
suffix = suffix [1 :]
582
586
583
- // Codes [AFM ] have an integer operand.
587
+ // Codes [AFMTr ] have an integer operand.
584
588
var index int
585
589
switch code {
586
- case opAt , opField , opMethod , opTypeParam :
590
+ case opAt , opField , opMethod , opTypeParam , opRecvTypeParam :
587
591
rest := strings .TrimLeft (suffix , "0123456789" )
588
592
numerals := suffix [:len (suffix )- len (rest )]
589
593
suffix = rest
@@ -664,6 +668,17 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
664
668
}
665
669
t = tparams .At (index )
666
670
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
+
667
682
case opConstraint :
668
683
tparam , ok := t .(* types.TypeParam )
669
684
if ! ok {
@@ -725,6 +740,10 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
725
740
}
726
741
}
727
742
743
+ if obj == nil {
744
+ panic (p ) // path does not end in an object-valued operator
745
+ }
746
+
728
747
if obj .Pkg () != pkg {
729
748
return nil , fmt .Errorf ("path denotes %s, which belongs to a different package" , obj )
730
749
}
0 commit comments