go/types, types2: explicitly check for non-nil type in LookupFieldOrMethod

Document and enforce API expectation. Add a test so we don't
inadvertently change the function behavior with respect to nil
type arguments.

Fixes #50620.

Change-Id: Ic000bff7504a03006bd248a319c7a2d49dcf09c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/379374
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Griesemer 2022-01-18 19:58:14 -08:00
parent 985d97e602
commit efbecc7eff
4 changed files with 34 additions and 2 deletions

View file

@ -1443,6 +1443,18 @@ var _ = a.C2
makePkg("main", mainSrc) // don't crash when type-checking this package
}
func TestLookupFieldOrMethodOnNil(t *testing.T) {
// LookupFieldOrMethod on a nil type is expected to produce a run-time panic.
defer func() {
const want = "LookupFieldOrMethod on nil type"
p := recover()
if s, ok := p.(string); !ok || s != want {
t.Fatalf("got %v, want %s", p, want)
}
}()
LookupFieldOrMethod(nil, false, nil, "")
}
func TestLookupFieldOrMethod(t *testing.T) {
// Test cases assume a lookup of the form a.f or x.f, where a stands for an
// addressable value, and x for a non-addressable value (even though a variable

View file

@ -19,7 +19,7 @@ import (
// in T and returns the corresponding *Var or *Func, an index sequence, and a
// bool indicating if there were any pointer indirections on the path to the
// field or method. If addressable is set, T is the type of an addressable
// variable (only matters for method lookups).
// variable (only matters for method lookups). T must not be nil.
//
// The last index entry is the field or method index in the (possibly embedded)
// type where the entry was found, either:
@ -42,6 +42,10 @@ import (
// the method's formal receiver base type, nor was the receiver addressable.
//
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
if T == nil {
panic("LookupFieldOrMethod on nil type")
}
// Methods cannot be associated to a named pointer type.
// (spec: "The type denoted by T is called the receiver base type;
// it must not be a pointer or interface type and it must be declared

View file

@ -1426,6 +1426,18 @@ var _ = a.C2
makePkg("main", mainSrc) // don't crash when type-checking this package
}
func TestLookupFieldOrMethodOnNil(t *testing.T) {
// LookupFieldOrMethod on a nil type is expected to produce a run-time panic.
defer func() {
const want = "LookupFieldOrMethod on nil type"
p := recover()
if s, ok := p.(string); !ok || s != want {
t.Fatalf("got %v, want %s", p, want)
}
}()
LookupFieldOrMethod(nil, false, nil, "")
}
func TestLookupFieldOrMethod(t *testing.T) {
// Test cases assume a lookup of the form a.f or x.f, where a stands for an
// addressable value, and x for a non-addressable value (even though a variable

View file

@ -19,7 +19,7 @@ import (
// in T and returns the corresponding *Var or *Func, an index sequence, and a
// bool indicating if there were any pointer indirections on the path to the
// field or method. If addressable is set, T is the type of an addressable
// variable (only matters for method lookups).
// variable (only matters for method lookups). T must not be nil.
//
// The last index entry is the field or method index in the (possibly embedded)
// type where the entry was found, either:
@ -42,6 +42,10 @@ import (
// the method's formal receiver base type, nor was the receiver addressable.
//
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
if T == nil {
panic("LookupFieldOrMethod on nil type")
}
// Methods cannot be associated to a named pointer type.
// (spec: "The type denoted by T is called the receiver base type;
// it must not be a pointer or interface type and it must be declared