}
case types.TINTER:
- for _, f := range t.FieldSlice() {
+ for _, f := range t.AllMethods().Slice() {
if types.IsExported(f.Sym.Name) {
p.markType(f.Type)
}
// TODO(mdempsky): Move to package types.
func method(typ *types.Type, index int) *types.Field {
if typ.IsInterface() {
- return typ.Field(index)
+ return typ.AllMethods().Index(index)
}
return types.ReceiverBaseType(typ).Methods().Index(index)
}
for i, f := range t.Methods().Slice() {
t2 := subst.typ(f.Type)
if (t2 != f.Type || f.Nname != nil) && newfields == nil {
- newfields = make([]*types.Field, t.NumFields())
+ newfields = make([]*types.Field, t.Methods().Len())
for j := 0; j < i; j++ {
- newfields[j] = t.Methods().Slice()[j]
+ newfields[j] = t.Methods().Index(j)
}
}
if newfields != nil {
// Compute the method set for t.
var ms *types.Fields
if t.IsInterface() {
- ms = t.Fields()
+ ms = t.AllMethods()
} else {
mt := types.ReceiverBaseType(t)
typecheck.CalcMethods(mt)
// imethods returns the methods of the interface type t, sorted by name.
func imethods(t *types.Type) []*typeSig {
var methods []*typeSig
- for _, f := range t.Fields().Slice() {
+ for _, f := range t.AllMethods().Slice() {
if f.Type.Kind() != types.TFUNC || f.Sym == nil {
continue
}
ms = append(ms, t.Methods().Slice()...)
sort.Sort(types.MethodsByName(ms))
- t.AllMethods().Set(ms)
+ t.SetAllMethods(ms)
}
// adddot1 returns the number of fields or methods named s at depth d in Type t.
return c, false
}
- for _, f := range u.Fields().Slice() {
+ var fields *types.Fields
+ if u.IsStruct() {
+ fields = u.Fields()
+ } else {
+ fields = u.AllMethods()
+ }
+ for _, f := range fields.Slice() {
if f.Embedded == 0 || f.Sym == nil {
continue
}
}
if u.IsInterface() {
- for _, f := range u.Fields().Slice() {
+ for _, f := range u.AllMethods().Slice() {
if f.Sym.Uniq() {
continue
}
}
if u.IsStruct() || u.IsInterface() {
- for _, f := range u.Fields().Slice() {
+ var fields *types.Fields
+ if u.IsStruct() {
+ fields = u.Fields()
+ } else {
+ fields = u.AllMethods()
+ }
+ for _, f := range fields.Slice() {
if f.Embedded == 0 {
continue
}
if t.IsInterface() {
i := 0
- tms := t.Fields().Slice()
- for _, im := range iface.Fields().Slice() {
+ tms := t.AllMethods().Slice()
+ for _, im := range iface.AllMethods().Slice() {
for i < len(tms) && tms[i].Sym != im.Sym {
i++
}
tms = t.AllMethods().Slice()
}
i := 0
- for _, im := range iface.Fields().Slice() {
+ for _, im := range iface.AllMethods().Slice() {
if im.Broke() {
continue
}
c := 0
if u.IsStruct() || u.IsInterface() {
- for _, f := range u.Fields().Slice() {
+ var fields *types.Fields
+ if u.IsStruct() {
+ fields = u.Fields()
+ } else {
+ fields = u.AllMethods()
+ }
+ for _, f := range fields.Slice() {
if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
if save != nil {
*save = f
// Compute the method set for t.
var ms *types.Fields
if t.IsInterface() {
- ms = t.Fields()
+ ms = t.AllMethods()
} else {
mt := types.ReceiverBaseType(t)
if mt == nil {
types.CalcSize(t)
var f1 *types.Field
- if t.IsStruct() || t.IsInterface() {
+ if t.IsStruct() {
f1 = Lookdot1(n, s, t, t.Fields(), dostrcmp)
+ } else if t.IsInterface() {
+ f1 = Lookdot1(n, s, t, t.AllMethods(), dostrcmp)
}
var f2 *types.Field
break
}
b.WriteString("interface {")
- for i, f := range t.Fields().Slice() {
+ for i, f := range t.AllMethods().Slice() {
if i != 0 {
b.WriteByte(';')
}
}
tconv2(b, f.Type, 'S', mode, visited)
}
- if t.NumFields() != 0 {
+ if t.AllMethods().Len() != 0 {
b.WriteByte(' ')
}
b.WriteByte('}')
return true
case TINTER:
- if t1.NumFields() != t2.NumFields() {
+ if t1.AllMethods().Len() != t2.AllMethods().Len() {
return false
}
- for i, f1 := range t1.FieldSlice() {
- f2 := t2.Field(i)
+ for i, f1 := range t1.AllMethods().Slice() {
+ f2 := t2.AllMethods().Index(i)
if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
return false
}
// Embedded interface: duplicate all methods
// (including broken ones, if any) and add to t's
// method set.
- for _, t1 := range m.Type.Fields().Slice() {
+ for _, t1 := range m.Type.AllMethods().Slice() {
// Use m.Pos rather than t1.Pos to preserve embedding position.
f := NewField(m.Pos, t1.Sym, t1.Type)
addMethod(f, false)
m.Offset = int64(i) * int64(PtrSize)
}
- // Access fields directly to avoid recursively calling CalcSize
- // within Type.Fields().
- t.Extra.(*Interface).Fields.Set(methods)
+ t.SetAllMethods(methods)
}
func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 {
{Forward{}, 20, 32},
{Func{}, 28, 48},
{Struct{}, 16, 32},
- {Interface{}, 8, 16},
+ {Interface{}, 4, 8},
{Chan{}, 8, 16},
{Array{}, 12, 16},
{FuncArgs{}, 4, 8},
// Interface contains Type fields specific to interface types.
type Interface struct {
- Fields Fields
- pkg *Pkg
+ pkg *Pkg
}
// Ptr contains Type fields specific to pointer types.
return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone
}
+// Methods returns a pointer to the base methods (excluding embedding) for type t.
+// These can either be concrete methods (for non-interface types) or interface
+// methods (for interface types).
func (t *Type) Methods() *Fields {
- // TODO(mdempsky): Validate t?
return &t.methods
}
+// AllMethods returns a pointer to all the methods (including embedding) for type t.
+// For an interface type, this is the set of methods that are typically iterated over.
func (t *Type) AllMethods() *Fields {
- // TODO(mdempsky): Validate t?
+ if t.kind == TINTER {
+ // Calculate the full method set of an interface type on the fly
+ // now, if not done yet.
+ CalcSize(t)
+ }
return &t.allMethods
}
+// SetAllMethods sets the set of all methods (including embedding) for type t.
+// Use this method instead of t.AllMethods().Set(), which might call CalcSize() on
+// an uninitialized interface type.
+func (t *Type) SetAllMethods(fs []*Field) {
+ t.allMethods.Set(fs)
+}
+
+// Fields returns the fields of struct type t.
func (t *Type) Fields() *Fields {
- switch t.kind {
- case TSTRUCT:
- return &t.Extra.(*Struct).fields
- case TINTER:
- CalcSize(t)
- return &t.Extra.(*Interface).Fields
- }
- base.Fatalf("Fields: type %v does not have fields", t)
- return nil
+ t.wantEtype(TSTRUCT)
+ return &t.Extra.(*Struct).fields
}
-// Field returns the i'th field/method of struct/interface type t.
+// Field returns the i'th field of struct type t.
func (t *Type) Field(i int) *Field {
return t.Fields().Slice()[i]
}
-// FieldSlice returns a slice of containing all fields/methods of
-// struct/interface type t.
+// FieldSlice returns a slice of containing all fields of
+// a struct type t.
func (t *Type) FieldSlice() []*Field {
return t.Fields().Slice()
}
-// SetFields sets struct/interface type t's fields/methods to fields.
+// SetFields sets struct type t's fields to fields.
func (t *Type) SetFields(fields []*Field) {
// If we've calculated the width of t before,
// then some other type such as a function signature
t.Fields().Set(fields)
}
+// SetInterface sets the base methods of an interface type t.
func (t *Type) SetInterface(methods []*Field) {
t.wantEtype(TINTER)
t.Methods().Set(methods)
return CMPeq
case TINTER:
- tfs := t.FieldSlice()
- xfs := x.FieldSlice()
+ tfs := t.AllMethods().Slice()
+ xfs := x.AllMethods().Slice()
for i := 0; i < len(tfs) && i < len(xfs); i++ {
t1, x1 := tfs[i], xfs[i]
if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
// IsEmptyInterface reports whether t is an empty interface type.
func (t *Type) IsEmptyInterface() bool {
- return t.IsInterface() && t.NumFields() == 0
+ return t.IsInterface() && t.AllMethods().Len() == 0
}
// IsScalar reports whether 't' is a scalar Go type, e.g.