From 35f4fd1cd17cc072cd94ac35d5eea0753a4f3ba3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 19 Jul 2013 11:01:51 -0700 Subject: [PATCH] go.tools/go/types: use *Var instead of *Field for struct fields Temporarily remove Field objects in favor of Vars for struct fields. In forthcoming CL, Fields will play the symmetric role to Methods, and serve as lookup results including index information. R=adonovan CC=golang-dev https://golang.org/cl/11594043 --- go/types/api.go | 2 +- go/types/call.go | 2 +- go/types/gcimporter.go | 6 +++--- go/types/lookup.go | 6 +++--- go/types/methodset.go | 4 ++-- go/types/objects.go | 23 ++++++++--------------- go/types/sizes.go | 2 +- go/types/types.go | 6 +++--- go/types/typexpr.go | 4 ++-- ssa/promote.go | 4 ++-- ssa/testdata/objlookup.go | 4 ++-- 11 files changed, 28 insertions(+), 35 deletions(-) diff --git a/go/types/api.go b/go/types/api.go index 9d34474d..d87a98cf 100644 --- a/go/types/api.go +++ b/go/types/api.go @@ -76,7 +76,7 @@ type Config struct { // of the given struct fields, in bytes. Otherwise DefaultOffsetsof // is called. Offsetsof must implement the offset guarantees // required by the spec. - Offsetsof func(fields []*Field) []int64 + Offsetsof func(fields []*Var) []int64 // If Sizeof != nil, it is called to determine the size of the // given type. Otherwise, DefaultSizeof is called. Sizeof must diff --git a/go/types/call.go b/go/types/call.go index b92ca25a..8d81d705 100644 --- a/go/types/call.go +++ b/go/types/call.go @@ -261,7 +261,7 @@ func (check *checker) selector(x *operand, e *ast.SelectorExpr) { } else { // regular selector switch obj := obj.(type) { - case *Field: + case *Var: x.mode = variable x.typ = obj.typ diff --git a/go/types/gcimporter.go b/go/types/gcimporter.go index 7a06f6a8..5c95fa64 100644 --- a/go/types/gcimporter.go +++ b/go/types/gcimporter.go @@ -460,7 +460,7 @@ func (p *gcParser) parseName(materializePkg bool) (pkg *Package, name string) { // Field = Name Type [ string_lit ] . // -func (p *gcParser) parseField() (*Field, string) { +func (p *gcParser) parseField() (*Var, string) { pkg, name := p.parseName(true) typ := p.parseType() anonymous := false @@ -482,14 +482,14 @@ func (p *gcParser) parseField() (*Field, string) { if p.tok == scanner.String { tag = p.expect(scanner.String) } - return NewField(token.NoPos, pkg, name, typ, anonymous), tag + return NewFieldVar(token.NoPos, pkg, name, typ, anonymous), tag } // StructType = "struct" "{" [ FieldList ] "}" . // FieldList = Field { ";" Field } . // func (p *gcParser) parseStructType() Type { - var fields []*Field + var fields []*Var var tags []string p.expectKeyword("struct") diff --git a/go/types/lookup.go b/go/types/lookup.go index 296745bc..bd523dd0 100644 --- a/go/types/lookup.go +++ b/go/types/lookup.go @@ -12,7 +12,7 @@ package types // indirectly via different packages.) // LookupFieldOrMethod looks up a field or method with given package and name -// in typ and returns the corresponding *Field or *Func, an index sequence, +// in typ 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. // @@ -61,7 +61,7 @@ func LookupFieldOrMethod(typ Type, pkg *Package, name string) (obj Object, index // start the search with the underlying type *T if obj2, index2, indirect2 := lookupFieldOrMethod(u, pkg, name); obj2 != nil { // only if the result is a field can we keep it - if _, ok := obj2.(*Field); ok { + if _, ok := obj2.(*Var); ok { return obj2, index2, indirect2 } } @@ -293,7 +293,7 @@ func concat(list []int, i int) []int { } // fieldIndex returns the index for the field with matching package and name, or a value < 0. -func fieldIndex(fields []*Field, pkg *Package, name string) int { +func fieldIndex(fields []*Var, pkg *Package, name string) int { if name == "_" { return -1 // blank identifiers are never found } diff --git a/go/types/methodset.go b/go/types/methodset.go index 783450cc..9777c1bf 100644 --- a/go/types/methodset.go +++ b/go/types/methodset.go @@ -238,12 +238,12 @@ func NewMethodSet(typ Type) *MethodSet { // A fieldSet is a set of fields and name collisions. // A collision indicates that multiple fields with the // same unique name appeared. -type fieldSet map[string]*Field // a nil entry indicates a name collision +type fieldSet map[string]*Var // a nil entry indicates a name collision // Add adds field f to the field set s. // If multiples is set, f appears multiple times // and is treated as a collision. -func (s fieldSet) add(f *Field, multiples bool) fieldSet { +func (s fieldSet) add(f *Var, multiples bool) fieldSet { if s == nil { s = make(fieldSet) } diff --git a/go/types/objects.go b/go/types/objects.go index a188c971..a1eb03fe 100644 --- a/go/types/objects.go +++ b/go/types/objects.go @@ -156,31 +156,24 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { func (obj *TypeName) String() string { return obj.toString("type", obj.typ.Underlying()) } -// A Variable represents a declared variable (including function parameters and results). +// A Variable represents a declared variable (including function parameters and results, and struct fields). type Var struct { object - visited bool // for initialization cycle detection + anonymous bool // if set, this variable is an anonymous struct field, and name is the type name + visited bool // for initialization cycle detection } func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var { - return &Var{object{nil, pos, pkg, name, typ}, false} + return &Var{object{nil, pos, pkg, name, typ}, false, false} } -func (obj *Var) String() string { return obj.toString("var", obj.typ) } - -// A Field represents a struct field. -type Field struct { - object - anonymous bool +func NewFieldVar(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var { + return &Var{object{nil, pos, pkg, name, typ}, anonymous, false} } -func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Field { - return &Field{object{nil, pos, pkg, name, typ}, anonymous} -} - -func (obj *Field) String() string { return obj.toString("field", obj.typ) } -func (obj *Field) Anonymous() bool { return obj.anonymous } +func (obj *Var) Anonymous() bool { return obj.anonymous } +func (obj *Var) String() string { return obj.toString("var", obj.typ) } // A Func represents a declared function. type Func struct { diff --git a/go/types/sizes.go b/go/types/sizes.go index 90cb832c..ada1cfb4 100644 --- a/go/types/sizes.go +++ b/go/types/sizes.go @@ -107,7 +107,7 @@ func align(x, a int64) int64 { // DefaultOffsetsof implements the default field offset computation // for unsafe.Offsetof. It is used if Config.Offsetsof == nil. -func DefaultOffsetsof(fields []*Field) []int64 { +func DefaultOffsetsof(fields []*Var) []int64 { offsets := make([]int64, len(fields)) var o int64 for i, f := range fields { diff --git a/go/types/types.go b/go/types/types.go index 4b1f4337..0a459d21 100644 --- a/go/types/types.go +++ b/go/types/types.go @@ -124,7 +124,7 @@ func (s *Slice) Elem() Type { return s.elt } // A Struct represents a struct type. type Struct struct { - fields []*Field + fields []*Var tags []string // field tags; nil if there are no tags // TODO(gri) access to offsets is not threadsafe - fix this offsets []int64 // field offsets in bytes, lazily initialized @@ -135,7 +135,7 @@ type Struct struct { // If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be // only as long as required to hold the tag with the largest index i. Consequently, // if no field has a tag, tags may be nil. -func NewStruct(fields []*Field, tags []string) *Struct { +func NewStruct(fields []*Var, tags []string) *Struct { return &Struct{fields: fields, tags: tags} } @@ -143,7 +143,7 @@ func NewStruct(fields []*Field, tags []string) *Struct { func (s *Struct) NumFields() int { return len(s.fields) } // Field returns the i'th field for 0 <= i < NumFields(). -func (s *Struct) Field(i int) *Field { return s.fields[i] } +func (s *Struct) Field(i int) *Var { return s.fields[i] } // Tag returns the i'th field tag for 0 <= i < NumFields(). func (s *Struct) Tag(i int) string { diff --git a/go/types/typexpr.go b/go/types/typexpr.go index 1ed83680..345e80cb 100644 --- a/go/types/typexpr.go +++ b/go/types/typexpr.go @@ -395,7 +395,7 @@ func (check *checker) tag(t *ast.BasicLit) string { return "" } -func (check *checker) collectFields(list *ast.FieldList, cycleOk bool) (fields []*Field, tags []string) { +func (check *checker) collectFields(list *ast.FieldList, cycleOk bool) (fields []*Var, tags []string) { if list == nil { return } @@ -412,7 +412,7 @@ func (check *checker) collectFields(list *ast.FieldList, cycleOk bool) (fields [ tags = append(tags, tag) } - fld := NewField(pos, check.pkg, name, typ, anonymous) + fld := NewFieldVar(pos, check.pkg, name, typ, anonymous) check.declare(scope, ident, fld) fields = append(fields, fld) } diff --git a/ssa/promote.go b/ssa/promote.go index 7e49cdf2..f287f7ea 100644 --- a/ssa/promote.go +++ b/ssa/promote.go @@ -27,10 +27,10 @@ import ( type anonFieldPath struct { tail *anonFieldPath index int // index of field within enclosing types.Struct.Fields - field *types.Field + field *types.Var } -func (p *anonFieldPath) contains(f *types.Field) bool { +func (p *anonFieldPath) contains(f *types.Var) bool { for ; p != nil; p = p.tail { if p.field == f { return true diff --git a/ssa/testdata/objlookup.go b/ssa/testdata/objlookup.go index 560c30df..f8230e83 100644 --- a/ssa/testdata/objlookup.go +++ b/ssa/testdata/objlookup.go @@ -31,7 +31,7 @@ type I interface { } type S struct { - x int + x int // x::nil } func main() { @@ -73,7 +73,7 @@ func main() { print(v6) // v6::Const var v7 S // v7::UnOp (load from Alloc) - v7.x = 1 // &v7::Alloc + v7.x = 1 // &v7::Alloc x::nil TODO(adonovan): do better for x var v8 [1]int // v8::UnOp (load from Alloc) v8[0] = 0 // &v8::Alloc