mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: get rid of Fields in types.Interface, use allMethods in types.Type instead
Confusingly, the set of all methods of an interface is currently set in Fields field of types.Interface. This is true, even though there is already an allMethods field (and AllMethods method) of types.Type. Change so the set of all methods of an interface are stored in Type.allMethods, and Interface.Fields is removed. Update the comments for Methods and AllMethods. Change-Id: Ibc32bafae86831cba62606b079a855690612c759 Reviewed-on: https://go-review.googlesource.com/c/go/+/307209 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
6ed045b365
commit
a4b8241d97
12 changed files with 74 additions and 47 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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('}')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -368,7 +368,6 @@ func (t *Type) StructType() *Struct {
|
|||
|
||||
// Interface contains Type fields specific to interface types.
|
||||
type Interface struct {
|
||||
Fields Fields
|
||||
pkg *Pkg
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
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
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Field returns the i'th field/method of struct/interface type t.
|
||||
// Fields returns the fields of struct type t.
|
||||
func (t *Type) Fields() *Fields {
|
||||
t.wantEtype(TSTRUCT)
|
||||
return &t.Extra.(*Struct).fields
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue