go.tools/go/types: remove PackageObj Selection - not needed
LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/105920043
This commit is contained in:
parent
f59b01c69b
commit
d014be43ae
|
@ -78,8 +78,9 @@ func (info *PackageInfo) ObjectOf(id *ast.Ident) types.Object {
|
||||||
func (info *PackageInfo) IsType(e ast.Expr) bool {
|
func (info *PackageInfo) IsType(e ast.Expr) bool {
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
case *ast.SelectorExpr: // pkg.Type
|
case *ast.SelectorExpr: // pkg.Type
|
||||||
if sel := info.Selections[e]; sel.Kind() == types.PackageObj {
|
if _, ok := info.Selections[e]; !ok {
|
||||||
_, isType := sel.Obj().(*types.TypeName)
|
// qualified identifier
|
||||||
|
_, isType := info.Uses[e.Sel].(*types.TypeName)
|
||||||
return isType
|
return isType
|
||||||
}
|
}
|
||||||
case *ast.StarExpr: // *T
|
case *ast.StarExpr: // *T
|
||||||
|
|
|
@ -350,22 +350,20 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||||
return b.addr(fn, e.X, escaping)
|
return b.addr(fn, e.X, escaping)
|
||||||
|
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
switch sel := fn.Pkg.info.Selections[e]; sel.Kind() {
|
sel, ok := fn.Pkg.info.Selections[e]
|
||||||
case types.PackageObj:
|
if !ok {
|
||||||
obj := sel.Obj()
|
// qualified identifier
|
||||||
if v := fn.Prog.packageLevelValue(obj); v != nil {
|
return b.addr(fn, e.Sel, escaping)
|
||||||
return &address{addr: v, expr: e}
|
}
|
||||||
}
|
if sel.Kind() != types.FieldVal {
|
||||||
panic("undefined package-qualified name: " + obj.Name())
|
panic(sel)
|
||||||
|
}
|
||||||
case types.FieldVal:
|
wantAddr := true
|
||||||
wantAddr := true
|
v := b.receiver(fn, e.X, wantAddr, escaping, sel)
|
||||||
v := b.receiver(fn, e.X, wantAddr, escaping, sel)
|
last := len(sel.Index()) - 1
|
||||||
last := len(sel.Index()) - 1
|
return &address{
|
||||||
return &address{
|
addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel.Pos()),
|
||||||
addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel.Pos()),
|
expr: e.Sel,
|
||||||
expr: e.Sel,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.IndexExpr:
|
case *ast.IndexExpr:
|
||||||
|
@ -614,10 +612,12 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
|
||||||
return emitLoad(fn, fn.lookup(obj, false)) // var (address)
|
return emitLoad(fn, fn.lookup(obj, false)) // var (address)
|
||||||
|
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
switch sel := fn.Pkg.info.Selections[e]; sel.Kind() {
|
sel, ok := fn.Pkg.info.Selections[e]
|
||||||
case types.PackageObj:
|
if !ok {
|
||||||
|
// qualified identifier
|
||||||
return b.expr(fn, e.Sel)
|
return b.expr(fn, e.Sel)
|
||||||
|
}
|
||||||
|
switch sel.Kind() {
|
||||||
case types.MethodExpr:
|
case types.MethodExpr:
|
||||||
// (*T).f or T.f, the method f from the method-set of type T.
|
// (*T).f or T.f, the method f from the method-set of type T.
|
||||||
// The result is a "thunk".
|
// The result is a "thunk".
|
||||||
|
@ -749,47 +749,8 @@ func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
|
||||||
|
|
||||||
// Is this a method call?
|
// Is this a method call?
|
||||||
if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
|
if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
|
||||||
switch sel := fn.Pkg.info.Selections[selector]; sel.Kind() {
|
sel, ok := fn.Pkg.info.Selections[selector]
|
||||||
case types.PackageObj:
|
if ok && sel.Kind() == types.MethodVal {
|
||||||
// e.g. fmt.Println
|
|
||||||
|
|
||||||
case types.MethodExpr:
|
|
||||||
// T.f() or (*T).f(): a statically dispatched
|
|
||||||
// call to the method f in the method-set of T
|
|
||||||
// or *T. T may be an interface.
|
|
||||||
|
|
||||||
// e.Fun would evaluate to a concrete method,
|
|
||||||
// interface wrapper function, or promotion
|
|
||||||
// wrapper.
|
|
||||||
//
|
|
||||||
// For now, we evaluate it in the usual way.
|
|
||||||
|
|
||||||
// TODO(adonovan): opt: inline expr() here, to
|
|
||||||
// make the call static and to avoid
|
|
||||||
// generation of wrappers. It's somewhat
|
|
||||||
// tricky as it may consume the first actual
|
|
||||||
// parameter if the call is "invoke" mode.
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// type T struct{}; func (T) f() {} // "call" mode
|
|
||||||
// type T interface { f() } // "invoke" mode
|
|
||||||
//
|
|
||||||
// type S struct{ T }
|
|
||||||
//
|
|
||||||
// var s S
|
|
||||||
// S.f(s)
|
|
||||||
// (*S).f(&s)
|
|
||||||
//
|
|
||||||
// Suggested approach:
|
|
||||||
// - consume the first actual parameter expression
|
|
||||||
// and build it with b.expr().
|
|
||||||
// - apply implicit field selections.
|
|
||||||
// - use MethodVal logic to populate fields of c.
|
|
||||||
|
|
||||||
case types.FieldVal:
|
|
||||||
// A field access, not a method call.
|
|
||||||
|
|
||||||
case types.MethodVal:
|
|
||||||
obj := sel.Obj().(*types.Func)
|
obj := sel.Obj().(*types.Func)
|
||||||
wantAddr := isPointer(recvType(obj))
|
wantAddr := isPointer(recvType(obj))
|
||||||
escaping := true
|
escaping := true
|
||||||
|
@ -804,11 +765,37 @@ func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
|
||||||
c.Args = append(c.Args, v)
|
c.Args = append(c.Args, v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("illegal (%s).%s() call; X:%T",
|
|
||||||
fn.Pkg.typeOf(selector.X), selector.Sel.Name, selector.X))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
|
||||||
|
// a statically dispatched call to the method f in the
|
||||||
|
// method-set of T or *T. T may be an interface.
|
||||||
|
//
|
||||||
|
// e.Fun would evaluate to a concrete method, interface
|
||||||
|
// wrapper function, or promotion wrapper.
|
||||||
|
//
|
||||||
|
// For now, we evaluate it in the usual way.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): opt: inline expr() here, to make the
|
||||||
|
// call static and to avoid generation of wrappers.
|
||||||
|
// It's somewhat tricky as it may consume the first
|
||||||
|
// actual parameter if the call is "invoke" mode.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// type T struct{}; func (T) f() {} // "call" mode
|
||||||
|
// type T interface { f() } // "invoke" mode
|
||||||
|
//
|
||||||
|
// type S struct{ T }
|
||||||
|
//
|
||||||
|
// var s S
|
||||||
|
// S.f(s)
|
||||||
|
// (*S).f(&s)
|
||||||
|
//
|
||||||
|
// Suggested approach:
|
||||||
|
// - consume the first actual parameter expression
|
||||||
|
// and build it with b.expr().
|
||||||
|
// - apply implicit field selections.
|
||||||
|
// - use MethodVal logic to populate fields of c.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the function operand in the usual way.
|
// Evaluate the function operand in the usual way.
|
||||||
|
|
|
@ -170,7 +170,8 @@ type Info struct {
|
||||||
//
|
//
|
||||||
Implicits map[ast.Node]Object
|
Implicits map[ast.Node]Object
|
||||||
|
|
||||||
// Selections maps selector expressions to their corresponding selections.
|
// Selections maps selector expressions (excluding qualified identifiers)
|
||||||
|
// to their corresponding selections.
|
||||||
Selections map[*ast.SelectorExpr]*Selection
|
Selections map[*ast.SelectorExpr]*Selection
|
||||||
|
|
||||||
// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
|
// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
|
||||||
|
|
|
@ -267,7 +267,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||||
check.errorf(e.Pos(), "%s not exported by package %s", sel, ident)
|
check.errorf(e.Pos(), "%s not exported by package %s", sel, ident)
|
||||||
// ok to continue
|
// ok to continue
|
||||||
}
|
}
|
||||||
check.recordSelection(e, PackageObj, nil, exp, nil, false)
|
check.recordUse(e.Sel, exp)
|
||||||
// Simplified version of the code for *ast.Idents:
|
// Simplified version of the code for *ast.Idents:
|
||||||
// - imported objects are always fully initialized
|
// - imported objects are always fully initialized
|
||||||
switch exp := exp.(type) {
|
switch exp := exp.(type) {
|
||||||
|
|
|
@ -11,14 +11,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SelectionKind describes the kind of a selector expression x.f.
|
// SelectionKind describes the kind of a selector expression x.f
|
||||||
|
// (excluding qualified identifiers).
|
||||||
type SelectionKind int
|
type SelectionKind int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FieldVal SelectionKind = iota // x.f is a struct field selector
|
FieldVal SelectionKind = iota // x.f is a struct field selector
|
||||||
MethodVal // x.f is a method selector
|
MethodVal // x.f is a method selector
|
||||||
MethodExpr // x.f is a method expression
|
MethodExpr // x.f is a method expression
|
||||||
PackageObj // x.f is a qualified identifier
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Selection describes a selector expression x.f.
|
// A Selection describes a selector expression x.f.
|
||||||
|
@ -36,33 +36,23 @@ const (
|
||||||
// p.x FieldVal T x int {0} true
|
// p.x FieldVal T x int {0} true
|
||||||
// p.m MethodVal *T m func (e *T) m() {1, 0} true
|
// p.m MethodVal *T m func (e *T) m() {1, 0} true
|
||||||
// T.m MethodExpr T m func m(_ T) {1, 0} false
|
// T.m MethodExpr T m func m(_ T) {1, 0} false
|
||||||
// math.Pi PackageObj nil Pi untyped numeric nil false
|
|
||||||
//
|
//
|
||||||
type Selection struct {
|
type Selection struct {
|
||||||
kind SelectionKind
|
kind SelectionKind
|
||||||
recv Type // type of x, nil if kind == PackageObj
|
recv Type // type of x
|
||||||
obj Object // object denoted by x.f
|
obj Object // object denoted by x.f
|
||||||
index []int // path from x to x.f, nil if kind == PackageObj
|
index []int // path from x to x.f
|
||||||
indirect bool // set if there was any pointer indirection on the path, false if kind == PackageObj
|
indirect bool // set if there was any pointer indirection on the path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kind returns the selection kind.
|
// Kind returns the selection kind.
|
||||||
func (s *Selection) Kind() SelectionKind { return s.kind }
|
func (s *Selection) Kind() SelectionKind { return s.kind }
|
||||||
|
|
||||||
// Recv returns the type of x in x.f.
|
// Recv returns the type of x in x.f.
|
||||||
// The result is nil if x.f is a qualified identifier (PackageObj).
|
|
||||||
func (s *Selection) Recv() Type { return s.recv }
|
func (s *Selection) Recv() Type { return s.recv }
|
||||||
|
|
||||||
// Obj returns the object denoted by x.f.
|
// Obj returns the object denoted by x.f; a *Var for
|
||||||
// The following object types may appear:
|
// a field selection, and a *Func in all other cases.
|
||||||
//
|
|
||||||
// Kind Object
|
|
||||||
//
|
|
||||||
// FieldVal *Var field
|
|
||||||
// MethodVal *Func method
|
|
||||||
// MethodExpr *Func method
|
|
||||||
// PackageObj *Const, *Type, *Var, *Func imported const, type, var, or func
|
|
||||||
//
|
|
||||||
func (s *Selection) Obj() Object { return s.obj }
|
func (s *Selection) Obj() Object { return s.obj }
|
||||||
|
|
||||||
// Type returns the type of x.f, which may be different from the type of f.
|
// Type returns the type of x.f, which may be different from the type of f.
|
||||||
|
@ -100,8 +90,6 @@ func (s *Selection) Type() Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index describes the path from x to f in x.f.
|
// Index describes the path from x to f in x.f.
|
||||||
// The result is nil if x.f is a qualified identifier (PackageObj).
|
|
||||||
//
|
|
||||||
// The last index entry is the field or method index of the type declaring f;
|
// The last index entry is the field or method index of the type declaring f;
|
||||||
// either:
|
// either:
|
||||||
//
|
//
|
||||||
|
@ -115,7 +103,6 @@ func (s *Selection) Index() []int { return s.index }
|
||||||
|
|
||||||
// Indirect reports whether any pointer indirection was required to get from
|
// Indirect reports whether any pointer indirection was required to get from
|
||||||
// x to f in x.f.
|
// x to f in x.f.
|
||||||
// The result is false if x.f is a qualified identifier (PackageObj).
|
|
||||||
func (s *Selection) Indirect() bool { return s.indirect }
|
func (s *Selection) Indirect() bool { return s.indirect }
|
||||||
|
|
||||||
func (s *Selection) String() string { return SelectionString(nil, s) }
|
func (s *Selection) String() string { return SelectionString(nil, s) }
|
||||||
|
@ -128,7 +115,6 @@ func (s *Selection) String() string { return SelectionString(nil, s) }
|
||||||
// "field (T) f int"
|
// "field (T) f int"
|
||||||
// "method (T) f(X) Y"
|
// "method (T) f(X) Y"
|
||||||
// "method expr (T) f(X) Y"
|
// "method expr (T) f(X) Y"
|
||||||
// "qualified ident var math.Pi float64"
|
|
||||||
//
|
//
|
||||||
func SelectionString(this *Package, s *Selection) string {
|
func SelectionString(this *Package, s *Selection) string {
|
||||||
var k string
|
var k string
|
||||||
|
@ -139,8 +125,6 @@ func SelectionString(this *Package, s *Selection) string {
|
||||||
k = "method "
|
k = "method "
|
||||||
case MethodExpr:
|
case MethodExpr:
|
||||||
k = "method expr "
|
k = "method expr "
|
||||||
case PackageObj:
|
|
||||||
return fmt.Sprintf("qualified ident %s", s.obj)
|
|
||||||
default:
|
default:
|
||||||
unreachable()
|
unreachable()
|
||||||
}
|
}
|
||||||
|
@ -150,7 +134,6 @@ func SelectionString(this *Package, s *Selection) string {
|
||||||
WriteType(&buf, this, s.Recv())
|
WriteType(&buf, this, s.Recv())
|
||||||
fmt.Fprintf(&buf, ") %s", s.obj.Name())
|
fmt.Fprintf(&buf, ") %s", s.obj.Name())
|
||||||
if T := s.Type(); s.kind == FieldVal {
|
if T := s.Type(); s.kind == FieldVal {
|
||||||
// TODO(adonovan): use "T.f" not "(T) f".
|
|
||||||
buf.WriteByte(' ')
|
buf.WriteByte(' ')
|
||||||
WriteType(&buf, this, T)
|
WriteType(&buf, this, T)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -244,9 +244,10 @@ func NewTransformer(fset *token.FileSet, template *loader.PackageInfo, verbose b
|
||||||
// TODO reject dot-imports in pattern
|
// TODO reject dot-imports in pattern
|
||||||
ast.Inspect(after, func(n ast.Node) bool {
|
ast.Inspect(after, func(n ast.Node) bool {
|
||||||
if n, ok := n.(*ast.SelectorExpr); ok {
|
if n, ok := n.(*ast.SelectorExpr); ok {
|
||||||
sel := tr.info.Selections[n]
|
if _, ok := tr.info.Selections[n]; !ok {
|
||||||
if sel.Kind() == types.PackageObj {
|
// qualified ident
|
||||||
tr.importedObjs[sel.Obj()] = n
|
obj := tr.info.Uses[n.Sel]
|
||||||
|
tr.importedObjs[obj] = n
|
||||||
return false // prune
|
return false // prune
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,9 +217,9 @@ func isRef(n ast.Node, info *loader.PackageInfo) types.Object {
|
||||||
return info.Uses[n]
|
return info.Uses[n]
|
||||||
|
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
sel := info.Selections[n]
|
if _, ok := info.Selections[n]; !ok {
|
||||||
if sel.Kind() == types.PackageObj {
|
// qualified ident
|
||||||
return sel.Obj()
|
return info.Uses[n.Sel]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue