Skip to content

Commit c111c4d

Browse files
adonovangopherbot
authored andcommitted
internal/typesinternal: add ReceiverNamed helper
...and factor numerous places to use it. (This pattern kept recurring during my types.Alias audit, golang/go#65294.) Change-Id: I93228b735f7a8ff70df5c998017437d43742d9f3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/565075 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]> Reviewed-by: Tim King <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent a821e61 commit c111c4d

File tree

18 files changed

+91
-131
lines changed

18 files changed

+91
-131
lines changed

cmd/deadcode/deadcode.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
"golang.org/x/tools/go/packages"
3434
"golang.org/x/tools/go/ssa"
3535
"golang.org/x/tools/go/ssa/ssautil"
36-
"golang.org/x/tools/internal/aliases"
36+
"golang.org/x/tools/internal/typesinternal"
3737
)
3838

3939
//go:embed doc.go
@@ -385,11 +385,8 @@ func prettyName(fn *ssa.Function, qualified bool) string {
385385

386386
// method receiver?
387387
if recv := fn.Signature.Recv(); recv != nil {
388-
t := recv.Type()
389-
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
390-
t = ptr.Elem()
391-
}
392-
buf.WriteString(aliases.Unalias(t).(*types.Named).Obj().Name())
388+
_, named := typesinternal.ReceiverNamed(recv)
389+
buf.WriteString(named.Obj().Name())
393390
buf.WriteByte('.')
394391
}
395392

cmd/guru/describe.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"golang.org/x/tools/go/ast/astutil"
2020
"golang.org/x/tools/go/loader"
2121
"golang.org/x/tools/go/types/typeutil"
22+
"golang.org/x/tools/internal/typesinternal"
2223
)
2324

2425
// describe describes the syntax node denoted by the query position,
@@ -911,11 +912,7 @@ func accessibleFields(recv types.Type, from *types.Package) []describeField {
911912

912913
// Handle recursion through anonymous fields.
913914
if f.Anonymous() {
914-
tf := f.Type()
915-
if ptr, ok := tf.(*types.Pointer); ok {
916-
tf = ptr.Elem()
917-
}
918-
if named, ok := tf.(*types.Named); ok { // (be defensive)
915+
if _, named := typesinternal.ReceiverNamed(f); named != nil {
919916
// If we've already visited this named type
920917
// on this path, break the cycle.
921918
for _, x := range stack {

go/analysis/passes/httpmux/httpmux.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1818
"golang.org/x/tools/go/ast/inspector"
1919
"golang.org/x/tools/go/types/typeutil"
20+
"golang.org/x/tools/internal/typesinternal"
2021
)
2122

2223
const Doc = `report using Go 1.22 enhanced ServeMux patterns in older Go versions
@@ -83,11 +84,8 @@ func isServeMuxRegisterCall(pass *analysis.Pass, call *ast.CallExpr) bool {
8384
if !isMethodNamed(fn, "net/http", "Handle", "HandleFunc") {
8485
return false
8586
}
86-
t, ok := fn.Type().(*types.Signature).Recv().Type().(*types.Pointer)
87-
if !ok {
88-
return false
89-
}
90-
return analysisutil.IsNamedType(t.Elem(), "net/http", "ServeMux")
87+
isPtr, named := typesinternal.ReceiverNamed(fn.Type().(*types.Signature).Recv())
88+
return isPtr && analysisutil.IsNamedType(named, "net/http", "ServeMux")
9189
}
9290

9391
func isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {

go/analysis/passes/httpresponse/httpresponse.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"golang.org/x/tools/go/analysis/passes/inspect"
1515
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1616
"golang.org/x/tools/go/ast/inspector"
17+
"golang.org/x/tools/internal/typesinternal"
1718
)
1819

1920
const Doc = `check for mistakes using HTTP responses
@@ -116,7 +117,8 @@ func isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {
116117
if res.Len() != 2 {
117118
return false // the function called does not return two values.
118119
}
119-
if ptr, ok := res.At(0).Type().(*types.Pointer); !ok || !analysisutil.IsNamedType(ptr.Elem(), "net/http", "Response") {
120+
isPtr, named := typesinternal.ReceiverNamed(res.At(0))
121+
if !isPtr || !analysisutil.IsNamedType(named, "net/http", "Response") {
120122
return false // the first return type is not *http.Response.
121123
}
122124

go/analysis/passes/loopclosure/loopclosure.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1515
"golang.org/x/tools/go/ast/inspector"
1616
"golang.org/x/tools/go/types/typeutil"
17+
"golang.org/x/tools/internal/typesinternal"
1718
"golang.org/x/tools/internal/versions"
1819
)
1920

@@ -367,9 +368,6 @@ func isMethodCall(info *types.Info, expr ast.Expr, pkgPath, typeName, method str
367368

368369
// Check that the receiver is a <pkgPath>.<typeName> or
369370
// *<pkgPath>.<typeName>.
370-
rtype := recv.Type()
371-
if ptr, ok := recv.Type().(*types.Pointer); ok {
372-
rtype = ptr.Elem()
373-
}
374-
return analysisutil.IsNamedType(rtype, pkgPath, typeName)
371+
_, named := typesinternal.ReceiverNamed(recv)
372+
return analysisutil.IsNamedType(named, pkgPath, typeName)
375373
}

go/analysis/passes/slog/slog.go

+9-17
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
2121
"golang.org/x/tools/go/ast/inspector"
2222
"golang.org/x/tools/go/types/typeutil"
23+
"golang.org/x/tools/internal/typesinternal"
2324
)
2425

2526
//go:embed doc.go
@@ -150,14 +151,10 @@ func isAttr(t types.Type) bool {
150151
func shortName(fn *types.Func) string {
151152
var r string
152153
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
153-
t := recv.Type()
154-
if pt, ok := t.(*types.Pointer); ok {
155-
t = pt.Elem()
156-
}
157-
if nt, ok := t.(*types.Named); ok {
158-
r = nt.Obj().Name()
154+
if _, named := typesinternal.ReceiverNamed(recv); named != nil {
155+
r = named.Obj().Name()
159156
} else {
160-
r = recv.Type().String()
157+
r = recv.Type().String() // anon struct/interface
161158
}
162159
r += "."
163160
}
@@ -173,17 +170,12 @@ func kvFuncSkipArgs(fn *types.Func) (int, bool) {
173170
return 0, false
174171
}
175172
var recvName string // by default a slog package function
176-
recv := fn.Type().(*types.Signature).Recv()
177-
if recv != nil {
178-
t := recv.Type()
179-
if pt, ok := t.(*types.Pointer); ok {
180-
t = pt.Elem()
181-
}
182-
if nt, ok := t.(*types.Named); !ok {
183-
return 0, false
184-
} else {
185-
recvName = nt.Obj().Name()
173+
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
174+
_, named := typesinternal.ReceiverNamed(recv)
175+
if named == nil {
176+
return 0, false // anon struct/interface
186177
}
178+
recvName = named.Obj().Name()
187179
}
188180
skip, ok := kvFuncs[recvName][fn.Name()]
189181
return skip, ok

go/analysis/passes/unmarshal/unmarshal.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1515
"golang.org/x/tools/go/ast/inspector"
1616
"golang.org/x/tools/go/types/typeutil"
17+
"golang.org/x/tools/internal/typesinternal"
1718
)
1819

1920
//go:embed doc.go
@@ -69,12 +70,8 @@ func run(pass *analysis.Pass) (interface{}, error) {
6970
// (*"encoding/json".Decoder).Decode
7071
// (* "encoding/gob".Decoder).Decode
7172
// (* "encoding/xml".Decoder).Decode
72-
t := recv.Type()
73-
if ptr, ok := t.(*types.Pointer); ok {
74-
t = ptr.Elem()
75-
}
76-
tname := t.(*types.Named).Obj()
77-
if tname.Name() == "Decoder" {
73+
_, named := typesinternal.ReceiverNamed(recv)
74+
if tname := named.Obj(); tname.Name() == "Decoder" {
7875
switch tname.Pkg().Path() {
7976
case "encoding/json", "encoding/xml", "encoding/gob":
8077
argidx = 0 // func(interface{})

go/analysis/passes/unusedwrite/unusedwrite.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"golang.org/x/tools/go/analysis/passes/buildssa"
1414
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1515
"golang.org/x/tools/go/ssa"
16+
"golang.org/x/tools/internal/aliases"
1617
)
1718

1819
//go:embed doc.go
@@ -159,10 +160,13 @@ func hasStructOrArrayType(v ssa.Value) bool {
159160
//
160161
// For example, for struct T {x int, y int), getFieldName(*T, 1) returns "y".
161162
func getFieldName(tp types.Type, index int) string {
162-
if pt, ok := tp.(*types.Pointer); ok {
163+
// TODO(adonovan): use
164+
// stp, ok := typeparams.Deref(tp).Underlying().(*types.Struct); ok {
165+
// when Deref is defined.
166+
if pt, ok := aliases.Unalias(tp).(*types.Pointer); ok {
163167
tp = pt.Elem()
164168
}
165-
if named, ok := tp.(*types.Named); ok {
169+
if named, ok := aliases.Unalias(tp).(*types.Named); ok {
166170
tp = named.Underlying()
167171
}
168172
if stp, ok := tp.(*types.Struct); ok {

go/ssa/util.go

+8-11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"golang.org/x/tools/go/ast/astutil"
1919
"golang.org/x/tools/go/types/typeutil"
2020
"golang.org/x/tools/internal/typeparams"
21+
"golang.org/x/tools/internal/typesinternal"
2122
)
2223

2324
//// Sanity checking utilities
@@ -180,17 +181,13 @@ func makeLen(T types.Type) *Builtin {
180181
}
181182
}
182183

183-
// receiverTypeArgs returns the type arguments to a function's receiver.
184-
// Returns an empty list if obj does not have a receiver or its receiver does not have type arguments.
185-
func receiverTypeArgs(obj *types.Func) []types.Type {
186-
rtype := recvType(obj)
187-
if rtype == nil {
188-
return nil
189-
}
190-
rtype, _ = deptr(rtype)
191-
named, ok := rtype.(*types.Named)
192-
if !ok {
193-
return nil
184+
// receiverTypeArgs returns the type arguments to a method's receiver.
185+
// Returns an empty list if the receiver does not have type arguments.
186+
func receiverTypeArgs(method *types.Func) []types.Type {
187+
recv := method.Type().(*types.Signature).Recv()
188+
_, named := typesinternal.ReceiverNamed(recv)
189+
if named == nil {
190+
return nil // recv is anonymous struct/interface
194191
}
195192
ts := named.TypeArgs()
196193
if ts.Len() == 0 {

go/types/objectpath/objectpath.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"strings"
3131

3232
"golang.org/x/tools/internal/typeparams"
33+
"golang.org/x/tools/internal/typesinternal"
3334
)
3435

3536
// A Path is an opaque name that identifies a types.Object
@@ -395,13 +396,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
395396
return "", false
396397
}
397398

398-
recvT := meth.Type().(*types.Signature).Recv().Type()
399-
if ptr, ok := recvT.(*types.Pointer); ok {
400-
recvT = ptr.Elem()
401-
}
402-
403-
named, ok := recvT.(*types.Named)
404-
if !ok {
399+
_, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
400+
if named == nil {
405401
return "", false
406402
}
407403

gopls/internal/golang/code_lens.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"golang.org/x/tools/gopls/internal/file"
1818
"golang.org/x/tools/gopls/internal/protocol"
1919
"golang.org/x/tools/gopls/internal/protocol/command"
20+
"golang.org/x/tools/internal/typesinternal"
2021
)
2122

2223
type LensFunc func(context.Context, *cache.Snapshot, file.Handle) ([]protocol.CodeLens, error)
@@ -152,12 +153,8 @@ func matchTestFunc(fn *ast.FuncDecl, pkg *cache.Package, nameRe *regexp.Regexp,
152153
}
153154

154155
// Check the type of the only parameter
155-
paramTyp, ok := sig.Params().At(0).Type().(*types.Pointer)
156-
if !ok {
157-
return false
158-
}
159-
named, ok := paramTyp.Elem().(*types.Named)
160-
if !ok {
156+
isptr, named := typesinternal.ReceiverNamed(sig.Params().At(0))
157+
if !isptr || named == nil {
161158
return false
162159
}
163160
namedObj := named.Obj()

gopls/internal/golang/hover.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"golang.org/x/tools/gopls/internal/util/typesutil"
3939
"golang.org/x/tools/internal/event"
4040
"golang.org/x/tools/internal/tokeninternal"
41+
"golang.org/x/tools/internal/typesinternal"
4142
)
4243

4344
// hoverJSON contains the structured result of a hover query. It is
@@ -1235,11 +1236,7 @@ func promotedFields(t types.Type, from *types.Package) []promotedField {
12351236

12361237
// Handle recursion through anonymous fields.
12371238
if f.Anonymous() {
1238-
tf := f.Type()
1239-
if ptr, ok := tf.(*types.Pointer); ok {
1240-
tf = ptr.Elem()
1241-
}
1242-
if named, ok := tf.(*types.Named); ok { // (be defensive)
1239+
if _, named := typesinternal.ReceiverNamed(f); named != nil {
12431240
// If we've already visited this named type
12441241
// on this path, break the cycle.
12451242
for _, x := range stack {

gopls/internal/golang/rename.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import (
6969
"golang.org/x/tools/internal/diff"
7070
"golang.org/x/tools/internal/event"
7171
"golang.org/x/tools/internal/typeparams"
72+
"golang.org/x/tools/internal/typesinternal"
7273
"golang.org/x/tools/refactor/satisfy"
7374
)
7475

@@ -1189,12 +1190,8 @@ func (r *renamer) updateCommentDocLinks() (map[protocol.DocumentURI][]diff.Edit,
11891190
if recv == nil {
11901191
continue
11911192
}
1192-
recvT := recv.Type()
1193-
if ptr, ok := recvT.(*types.Pointer); ok {
1194-
recvT = ptr.Elem()
1195-
}
1196-
named, isNamed := recvT.(*types.Named)
1197-
if !isNamed {
1193+
_, named := typesinternal.ReceiverNamed(recv)
1194+
if named == nil {
11981195
continue
11991196
}
12001197
// Doc links can't reference interface methods.

internal/apidiff/compatibility.go

+9-22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"reflect"
1111

1212
"golang.org/x/tools/internal/aliases"
13+
"golang.org/x/tools/internal/typesinternal"
1314
)
1415

1516
func (d *differ) checkCompatible(otn *types.TypeName, old, new types.Type) {
@@ -305,7 +306,8 @@ func (d *differ) checkMethodSet(otn *types.TypeName, oldt, newt types.Type, addc
305306
// T and one for the embedded type U. We want both messages to appear,
306307
// but the messageSet dedup logic will allow only one message for a given
307308
// object. So use the part string to distinguish them.
308-
if receiverNamedType(oldMethod).Obj() != otn {
309+
recv := oldMethod.Type().(*types.Signature).Recv()
310+
if _, named := typesinternal.ReceiverNamed(recv); named.Obj() != otn {
309311
part = fmt.Sprintf(", method set of %s", msname)
310312
}
311313
d.incompatible(oldMethod, part, "removed")
@@ -336,34 +338,19 @@ func (d *differ) checkMethodSet(otn *types.TypeName, oldt, newt types.Type, addc
336338
}
337339

338340
// exportedMethods collects all the exported methods of type's method set.
339-
func exportedMethods(t types.Type) map[string]types.Object {
340-
m := map[string]types.Object{}
341+
func exportedMethods(t types.Type) map[string]*types.Func {
342+
m := make(map[string]*types.Func)
341343
ms := types.NewMethodSet(t)
342344
for i := 0; i < ms.Len(); i++ {
343-
obj := ms.At(i).Obj()
345+
obj := ms.At(i).Obj().(*types.Func)
344346
if obj.Exported() {
345347
m[obj.Name()] = obj
346348
}
347349
}
348350
return m
349351
}
350352

351-
func receiverType(method types.Object) types.Type {
352-
return method.Type().(*types.Signature).Recv().Type()
353-
}
354-
355-
func receiverNamedType(method types.Object) *types.Named {
356-
switch t := aliases.Unalias(receiverType(method)).(type) {
357-
case *types.Pointer:
358-
return aliases.Unalias(t.Elem()).(*types.Named)
359-
case *types.Named:
360-
return t
361-
default:
362-
panic("unreachable")
363-
}
364-
}
365-
366-
func hasPointerReceiver(method types.Object) bool {
367-
_, ok := aliases.Unalias(receiverType(method)).(*types.Pointer)
368-
return ok
353+
func hasPointerReceiver(method *types.Func) bool {
354+
isptr, _ := typesinternal.ReceiverNamed(method.Type().(*types.Signature).Recv())
355+
return isptr
369356
}

internal/gcimporter/gcimporter.go

-7
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
259259
return
260260
}
261261

262-
func deref(typ types.Type) types.Type {
263-
if p, _ := typ.(*types.Pointer); p != nil {
264-
return p.Elem()
265-
}
266-
return typ
267-
}
268-
269262
type byPath []*types.Package
270263

271264
func (a byPath) Len() int { return len(a) }

0 commit comments

Comments
 (0)