Skip to content

Commit 0106462

Browse files
committed
go/types: add Func.Signature method
Unfortunately we can't enforce the repr invariant that Func.typ != nil without thinking about the object color invariants. For now, return a trivial Signature if typ == nil, which should never happen in bug-free client code. Fixes #65772 Change-Id: I7f89c6d8fdc8dcd4b8880572e54bb0ed9b6136eb Reviewed-on: https://go-review.googlesource.com/c/go/+/565375 Commit-Queue: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent dfc86e9 commit 0106462

File tree

9 files changed

+57
-12
lines changed

9 files changed

+57
-12
lines changed

api/next/65772.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg go/types, method (*Func) Signature() *Signature #65772
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The [`Func`](/go/types#Func) type, which represents a function or
2+
method symbol, now has a [`Signature`](/go/types#Func.Signature)
3+
method that returns the function's type, which is always a
4+
`Signature`.

src/cmd/compile/internal/types2/object.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,34 @@ type Func struct {
374374
// NewFunc returns a new function with the given signature, representing
375375
// the function's type.
376376
func NewFunc(pos syntax.Pos, pkg *Package, name string, sig *Signature) *Func {
377-
// don't store a (typed) nil signature
378377
var typ Type
379378
if sig != nil {
380379
typ = sig
380+
} else {
381+
// Don't store a (typed) nil *Signature.
382+
// We can't simply replace it with new(Signature) either,
383+
// as this would violate object.{Type,color} invariants.
384+
// TODO(adonovan): propose to disallow NewFunc with nil *Signature.
381385
}
382386
return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false, nil}
383387
}
384388

389+
// Signature returns the signature (type) of the function or method.
390+
func (obj *Func) Signature() *Signature {
391+
if obj.typ != nil {
392+
return obj.typ.(*Signature) // normal case
393+
}
394+
// No signature: Signature was called either:
395+
// - within go/types, before a FuncDecl's initially
396+
// nil Func.Type was lazily populated, indicating
397+
// a types bug; or
398+
// - by a client after NewFunc(..., nil),
399+
// which is arguably a client bug, but we need a
400+
// proposal to tighten NewFunc's precondition.
401+
// For now, return a trivial signature.
402+
return new(Signature)
403+
}
404+
385405
// FullName returns the package- or receiver-type-qualified name of
386406
// function or method obj.
387407
func (obj *Func) FullName() string {

src/cmd/compile/internal/types2/subst.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ func (subst *subster) termlist(in []*Term) (out []*Term, copied bool) {
421421
func replaceRecvType(in []*Func, old, new Type) (out []*Func, copied bool) {
422422
out = in
423423
for i, method := range in {
424-
sig := method.Type().(*Signature)
424+
sig := method.Signature()
425425
if sig.recv != nil && sig.recv.Type() == old {
426426
if !copied {
427427
// Allocate a new methods slice before mutating for the first time.

src/go/types/api_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,7 +2324,7 @@ func f(x int) { y := x; print(y) }
23242324
wantParent = false
23252325
}
23262326
case *Func:
2327-
if obj.Type().(*Signature).Recv() != nil { // method
2327+
if obj.Signature().Recv() != nil { // method
23282328
wantParent = false
23292329
}
23302330
}
@@ -2615,9 +2615,9 @@ func fn() {
26152615

26162616
// Methods and method fields
26172617
{"concreteMethod", lookup("t").(*Named).Method(0)},
2618-
{"recv", lookup("t").(*Named).Method(0).Type().(*Signature).Recv()},
2619-
{"mParam", lookup("t").(*Named).Method(0).Type().(*Signature).Params().At(0)},
2620-
{"mResult", lookup("t").(*Named).Method(0).Type().(*Signature).Results().At(0)},
2618+
{"recv", lookup("t").(*Named).Method(0).Signature().Recv()},
2619+
{"mParam", lookup("t").(*Named).Method(0).Signature().Params().At(0)},
2620+
{"mResult", lookup("t").(*Named).Method(0).Signature().Results().At(0)},
26212621

26222622
// Interface methods
26232623
{"interfaceMethod", lookup("i").Underlying().(*Interface).Method(0)},

src/go/types/issues_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ type T struct{} // receiver type after method declaration
115115
}
116116

117117
m := f.Decls[0].(*ast.FuncDecl)
118-
res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
118+
res1 := defs[m.Name].(*Func).Signature().Results().At(0)
119119
res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
120120

121121
if res1 != res2 {
@@ -369,7 +369,7 @@ func TestIssue28005(t *testing.T) {
369369
// must match the method's name per the choice in the source file.
370370
for i := 0; i < iface.NumMethods(); i++ {
371371
m := iface.Method(i)
372-
recvName := m.Type().(*Signature).Recv().Type().(*Named).Obj().Name()
372+
recvName := m.Signature().Recv().Type().(*Named).Obj().Name()
373373
if recvName != m.Name() {
374374
t.Errorf("perm %v: got recv %s; want %s", perm, recvName, m.Name())
375375
}

src/go/types/object.go

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/go/types/resolver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,8 @@ func (check *Checker) collectObjects() {
395395
check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec})
396396
case funcDecl:
397397
name := d.decl.Name.Name
398-
obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil)
399-
hasTParamError := false // avoid duplicate type parameter errors
398+
obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil) // signature set later
399+
hasTParamError := false // avoid duplicate type parameter errors
400400
if d.decl.Recv.NumFields() == 0 {
401401
// regular function
402402
if d.decl.Recv != nil {

src/go/types/subst.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)