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:
Alan Donovan 2014-06-12 18:05:33 -04:00
parent f59b01c69b
commit d014be43ae
7 changed files with 71 additions and 98 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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) {

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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