diff options
-rw-r--r-- | src/cmd/compile/internal/gc/export.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/helpers.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/stencil.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/transform.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/reflectdata/reflect.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/typecheck/subr.go | 34 | ||||
-rw-r--r-- | src/cmd/compile/internal/typecheck/typecheck.go | 6 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/fmt.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/identity.go | 6 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/size.go | 6 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/sizeof_test.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types/type.go | 49 |
12 files changed, 73 insertions, 46 deletions
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 4d8221f53b..2137f1d196 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -152,7 +152,7 @@ func (p *exporter) markType(t *types.Type) { } case types.TINTER: - for _, f := range t.FieldSlice() { + for _, f := range t.AllMethods().Slice() { if types.IsExported(f.Sym.Name) { p.markType(f.Type) } diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 6320b30e50..9da0e49300 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -259,7 +259,7 @@ func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Fi // 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) } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 4db688571e..0d84db9993 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -625,9 +625,9 @@ func (subst *subster) tinter(t *types.Type) *types.Type { 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 { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 021d3a9fa7..ffe35d5874 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -568,7 +568,7 @@ func transformMethodExpr(n *ir.SelectorExpr) (res ir.Node) { // 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) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index c1cded826c..3a31e3c951 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -364,7 +364,7 @@ func methods(t *types.Type) []*typeSig { // 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 } diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index daf5cd72a2..76c565ebee 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -221,7 +221,7 @@ func CalcMethods(t *types.Type) { 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. @@ -257,7 +257,13 @@ func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase 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 } @@ -619,7 +625,7 @@ func expand0(t *types.Type) { } if u.IsInterface() { - for _, f := range u.Fields().Slice() { + for _, f := range u.AllMethods().Slice() { if f.Sym.Uniq() { continue } @@ -658,7 +664,13 @@ func expand1(t *types.Type, top bool) { } 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 } @@ -708,8 +720,8 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool 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++ } @@ -738,7 +750,7 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool tms = t.AllMethods().Slice() } i := 0 - for _, im := range iface.Fields().Slice() { + for _, im := range iface.AllMethods().Slice() { if im.Broke() { continue } @@ -806,7 +818,13 @@ func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) 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 diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 54f7cd9efa..ab493e0caa 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -1103,7 +1103,7 @@ func typecheckMethodExpr(n *ir.SelectorExpr) (res ir.Node) { // 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 { @@ -1170,8 +1170,10 @@ func Lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field { 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 diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index e29c826bb7..b538ea8054 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -442,7 +442,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type break } b.WriteString("interface {") - for i, f := range t.Fields().Slice() { + for i, f := range t.AllMethods().Slice() { if i != 0 { b.WriteByte(';') } @@ -462,7 +462,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } tconv2(b, f.Type, 'S', mode, visited) } - if t.NumFields() != 0 { + if t.AllMethods().Len() != 0 { b.WriteByte(' ') } b.WriteByte('}') diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index 9bc636d7ff..dde9f51856 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -61,11 +61,11 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b 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 } diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index a75429f0ab..f0e695ab96 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -119,7 +119,7 @@ func expandiface(t *Type) { // 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) @@ -135,9 +135,7 @@ func expandiface(t *Type) { 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 { diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go index f80de937be..4c3ef69346 100644 --- a/src/cmd/compile/internal/types/sizeof_test.go +++ b/src/cmd/compile/internal/types/sizeof_test.go @@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) { {Forward{}, 20, 32}, {Func{}, 28, 48}, {Struct{}, 16, 32}, - {Interface{}, 8, 16}, + {Interface{}, 4, 8}, {Chan{}, 8, 16}, {Array{}, 12, 16}, {FuncArgs{}, 4, 8}, diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 762cdd3258..969195b850 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -368,8 +368,7 @@ func (t *Type) StructType() *Struct { // 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. @@ -922,40 +921,49 @@ func (t *Type) IsFuncArgStruct() bool { 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 @@ -981,6 +989,7 @@ func (t *Type) SetFields(fields []*Field) { 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) @@ -1231,8 +1240,8 @@ func (t *Type) cmp(x *Type) Cmp { 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 { @@ -1420,7 +1429,7 @@ func (t *Type) IsInterface() bool { // 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. |