aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/gc/export.go2
-rw-r--r--src/cmd/compile/internal/noder/helpers.go2
-rw-r--r--src/cmd/compile/internal/noder/stencil.go4
-rw-r--r--src/cmd/compile/internal/noder/transform.go2
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go2
-rw-r--r--src/cmd/compile/internal/typecheck/subr.go34
-rw-r--r--src/cmd/compile/internal/typecheck/typecheck.go6
-rw-r--r--src/cmd/compile/internal/types/fmt.go4
-rw-r--r--src/cmd/compile/internal/types/identity.go6
-rw-r--r--src/cmd/compile/internal/types/size.go6
-rw-r--r--src/cmd/compile/internal/types/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types/type.go49
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.