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 {
|
||||
switch e := e.(type) {
|
||||
case *ast.SelectorExpr: // pkg.Type
|
||||
if sel := info.Selections[e]; sel.Kind() == types.PackageObj {
|
||||
_, isType := sel.Obj().(*types.TypeName)
|
||||
if _, ok := info.Selections[e]; !ok {
|
||||
// qualified identifier
|
||||
_, isType := info.Uses[e.Sel].(*types.TypeName)
|
||||
return isType
|
||||
}
|
||||
case *ast.StarExpr: // *T
|
||||
|
|
|
@ -350,15 +350,14 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
|||
return b.addr(fn, e.X, escaping)
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
switch sel := fn.Pkg.info.Selections[e]; sel.Kind() {
|
||||
case types.PackageObj:
|
||||
obj := sel.Obj()
|
||||
if v := fn.Prog.packageLevelValue(obj); v != nil {
|
||||
return &address{addr: v, expr: e}
|
||||
sel, ok := fn.Pkg.info.Selections[e]
|
||||
if !ok {
|
||||
// qualified identifier
|
||||
return b.addr(fn, e.Sel, escaping)
|
||||
}
|
||||
if sel.Kind() != types.FieldVal {
|
||||
panic(sel)
|
||||
}
|
||||
panic("undefined package-qualified name: " + obj.Name())
|
||||
|
||||
case types.FieldVal:
|
||||
wantAddr := true
|
||||
v := b.receiver(fn, e.X, wantAddr, escaping, sel)
|
||||
last := len(sel.Index()) - 1
|
||||
|
@ -366,7 +365,6 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
|||
addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel.Pos()),
|
||||
expr: e.Sel,
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.IndexExpr:
|
||||
var x Value
|
||||
|
@ -614,10 +612,12 @@ func (b *builder) expr0(fn *Function, e ast.Expr) Value {
|
|||
return emitLoad(fn, fn.lookup(obj, false)) // var (address)
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
switch sel := fn.Pkg.info.Selections[e]; sel.Kind() {
|
||||
case types.PackageObj:
|
||||
sel, ok := fn.Pkg.info.Selections[e]
|
||||
if !ok {
|
||||
// qualified identifier
|
||||
return b.expr(fn, e.Sel)
|
||||
|
||||
}
|
||||
switch sel.Kind() {
|
||||
case types.MethodExpr:
|
||||
// (*T).f or T.f, the method f from the method-set of type T.
|
||||
// The result is a "thunk".
|
||||
|
@ -749,26 +749,37 @@ func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
|
|||
|
||||
// Is this a method call?
|
||||
if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
|
||||
switch sel := fn.Pkg.info.Selections[selector]; sel.Kind() {
|
||||
case types.PackageObj:
|
||||
// e.g. fmt.Println
|
||||
sel, ok := fn.Pkg.info.Selections[selector]
|
||||
if ok && sel.Kind() == types.MethodVal {
|
||||
obj := sel.Obj().(*types.Func)
|
||||
wantAddr := isPointer(recvType(obj))
|
||||
escaping := true
|
||||
v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
|
||||
if isInterface(deref(v.Type())) {
|
||||
// Invoke-mode call.
|
||||
c.Value = v
|
||||
c.Method = obj
|
||||
} else {
|
||||
// "Call"-mode call.
|
||||
c.Value = fn.Prog.declaredFunc(obj)
|
||||
c.Args = append(c.Args, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
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.
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
|
@ -785,30 +796,6 @@ func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
|
|||
// 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)
|
||||
wantAddr := isPointer(recvType(obj))
|
||||
escaping := true
|
||||
v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
|
||||
if isInterface(deref(v.Type())) {
|
||||
// Invoke-mode call.
|
||||
c.Value = v
|
||||
c.Method = obj
|
||||
} else {
|
||||
// "Call"-mode call.
|
||||
c.Value = fn.Prog.declaredFunc(obj)
|
||||
c.Args = append(c.Args, v)
|
||||
}
|
||||
return
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("illegal (%s).%s() call; X:%T",
|
||||
fn.Pkg.typeOf(selector.X), selector.Sel.Name, selector.X))
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the function operand in the usual way.
|
||||
|
|
|
@ -170,7 +170,8 @@ type Info struct {
|
|||
//
|
||||
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
|
||||
|
||||
// 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)
|
||||
// ok to continue
|
||||
}
|
||||
check.recordSelection(e, PackageObj, nil, exp, nil, false)
|
||||
check.recordUse(e.Sel, exp)
|
||||
// Simplified version of the code for *ast.Idents:
|
||||
// - imported objects are always fully initialized
|
||||
switch exp := exp.(type) {
|
||||
|
|
|
@ -11,14 +11,14 @@ import (
|
|||
"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
|
||||
|
||||
const (
|
||||
FieldVal SelectionKind = iota // x.f is a struct field selector
|
||||
MethodVal // x.f is a method selector
|
||||
MethodExpr // x.f is a method expression
|
||||
PackageObj // x.f is a qualified identifier
|
||||
)
|
||||
|
||||
// A Selection describes a selector expression x.f.
|
||||
|
@ -36,33 +36,23 @@ const (
|
|||
// p.x FieldVal T x int {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
|
||||
// math.Pi PackageObj nil Pi untyped numeric nil false
|
||||
//
|
||||
type Selection struct {
|
||||
kind SelectionKind
|
||||
recv Type // type of x, nil if kind == PackageObj
|
||||
recv Type // type of x
|
||||
obj Object // object denoted by x.f
|
||||
index []int // path from x to x.f, nil if kind == PackageObj
|
||||
indirect bool // set if there was any pointer indirection on the path, false if kind == PackageObj
|
||||
index []int // path from x to x.f
|
||||
indirect bool // set if there was any pointer indirection on the path
|
||||
}
|
||||
|
||||
// Kind returns the selection kind.
|
||||
func (s *Selection) Kind() SelectionKind { return s.kind }
|
||||
|
||||
// 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 }
|
||||
|
||||
// Obj returns the object denoted by x.f.
|
||||
// The following object types may appear:
|
||||
//
|
||||
// Kind Object
|
||||
//
|
||||
// FieldVal *Var field
|
||||
// MethodVal *Func method
|
||||
// MethodExpr *Func method
|
||||
// PackageObj *Const, *Type, *Var, *Func imported const, type, var, or func
|
||||
//
|
||||
// Obj returns the object denoted by x.f; a *Var for
|
||||
// a field selection, and a *Func in all other cases.
|
||||
func (s *Selection) Obj() Object { return s.obj }
|
||||
|
||||
// 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.
|
||||
// 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;
|
||||
// either:
|
||||
//
|
||||
|
@ -115,7 +103,6 @@ func (s *Selection) Index() []int { return s.index }
|
|||
|
||||
// Indirect reports whether any pointer indirection was required to get from
|
||||
// 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) String() string { return SelectionString(nil, s) }
|
||||
|
@ -128,7 +115,6 @@ func (s *Selection) String() string { return SelectionString(nil, s) }
|
|||
// "field (T) f int"
|
||||
// "method (T) f(X) Y"
|
||||
// "method expr (T) f(X) Y"
|
||||
// "qualified ident var math.Pi float64"
|
||||
//
|
||||
func SelectionString(this *Package, s *Selection) string {
|
||||
var k string
|
||||
|
@ -139,8 +125,6 @@ func SelectionString(this *Package, s *Selection) string {
|
|||
k = "method "
|
||||
case MethodExpr:
|
||||
k = "method expr "
|
||||
case PackageObj:
|
||||
return fmt.Sprintf("qualified ident %s", s.obj)
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
@ -150,7 +134,6 @@ func SelectionString(this *Package, s *Selection) string {
|
|||
WriteType(&buf, this, s.Recv())
|
||||
fmt.Fprintf(&buf, ") %s", s.obj.Name())
|
||||
if T := s.Type(); s.kind == FieldVal {
|
||||
// TODO(adonovan): use "T.f" not "(T) f".
|
||||
buf.WriteByte(' ')
|
||||
WriteType(&buf, this, T)
|
||||
} else {
|
||||
|
|
|
@ -244,9 +244,10 @@ func NewTransformer(fset *token.FileSet, template *loader.PackageInfo, verbose b
|
|||
// TODO reject dot-imports in pattern
|
||||
ast.Inspect(after, func(n ast.Node) bool {
|
||||
if n, ok := n.(*ast.SelectorExpr); ok {
|
||||
sel := tr.info.Selections[n]
|
||||
if sel.Kind() == types.PackageObj {
|
||||
tr.importedObjs[sel.Obj()] = n
|
||||
if _, ok := tr.info.Selections[n]; !ok {
|
||||
// qualified ident
|
||||
obj := tr.info.Uses[n.Sel]
|
||||
tr.importedObjs[obj] = n
|
||||
return false // prune
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,9 +217,9 @@ func isRef(n ast.Node, info *loader.PackageInfo) types.Object {
|
|||
return info.Uses[n]
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
sel := info.Selections[n]
|
||||
if sel.Kind() == types.PackageObj {
|
||||
return sel.Obj()
|
||||
if _, ok := info.Selections[n]; !ok {
|
||||
// qualified ident
|
||||
return info.Uses[n.Sel]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue