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:
|
case types.TINTER:
|
||||||
for _, f := range t.FieldSlice() {
|
for _, f := range t.AllMethods().Slice() {
|
||||||
if types.IsExported(f.Sym.Name) {
|
if types.IsExported(f.Sym.Name) {
|
||||||
p.markType(f.Type)
|
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.
|
// TODO(mdempsky): Move to package types.
|
||||||
func method(typ *types.Type, index int) *types.Field {
|
func method(typ *types.Type, index int) *types.Field {
|
||||||
if typ.IsInterface() {
|
if typ.IsInterface() {
|
||||||
return typ.Field(index)
|
return typ.AllMethods().Index(index)
|
||||||
}
|
}
|
||||||
return types.ReceiverBaseType(typ).Methods().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() {
|
for i, f := range t.Methods().Slice() {
|
||||||
t2 := subst.typ(f.Type)
|
t2 := subst.typ(f.Type)
|
||||||
if (t2 != f.Type || f.Nname != nil) && newfields == nil {
|
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++ {
|
for j := 0; j < i; j++ {
|
||||||
newfields[j] = t.Methods().Slice()[j]
|
newfields[j] = t.Methods().Index(j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newfields != nil {
|
if newfields != nil {
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,7 @@ func transformMethodExpr(n *ir.SelectorExpr) (res ir.Node) {
|
||||||
// Compute the method set for t.
|
// Compute the method set for t.
|
||||||
var ms *types.Fields
|
var ms *types.Fields
|
||||||
if t.IsInterface() {
|
if t.IsInterface() {
|
||||||
ms = t.Fields()
|
ms = t.AllMethods()
|
||||||
} else {
|
} else {
|
||||||
mt := types.ReceiverBaseType(t)
|
mt := types.ReceiverBaseType(t)
|
||||||
typecheck.CalcMethods(mt)
|
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.
|
// imethods returns the methods of the interface type t, sorted by name.
|
||||||
func imethods(t *types.Type) []*typeSig {
|
func imethods(t *types.Type) []*typeSig {
|
||||||
var methods []*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 {
|
if f.Type.Kind() != types.TFUNC || f.Sym == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ func CalcMethods(t *types.Type) {
|
||||||
|
|
||||||
ms = append(ms, t.Methods().Slice()...)
|
ms = append(ms, t.Methods().Slice()...)
|
||||||
sort.Sort(types.MethodsByName(ms))
|
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.
|
// 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
|
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 {
|
if f.Embedded == 0 || f.Sym == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -619,7 +625,7 @@ func expand0(t *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.IsInterface() {
|
if u.IsInterface() {
|
||||||
for _, f := range u.Fields().Slice() {
|
for _, f := range u.AllMethods().Slice() {
|
||||||
if f.Sym.Uniq() {
|
if f.Sym.Uniq() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -658,7 +664,13 @@ func expand1(t *types.Type, top bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.IsStruct() || u.IsInterface() {
|
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 {
|
if f.Embedded == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -708,8 +720,8 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
||||||
|
|
||||||
if t.IsInterface() {
|
if t.IsInterface() {
|
||||||
i := 0
|
i := 0
|
||||||
tms := t.Fields().Slice()
|
tms := t.AllMethods().Slice()
|
||||||
for _, im := range iface.Fields().Slice() {
|
for _, im := range iface.AllMethods().Slice() {
|
||||||
for i < len(tms) && tms[i].Sym != im.Sym {
|
for i < len(tms) && tms[i].Sym != im.Sym {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
@ -738,7 +750,7 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
||||||
tms = t.AllMethods().Slice()
|
tms = t.AllMethods().Slice()
|
||||||
}
|
}
|
||||||
i := 0
|
i := 0
|
||||||
for _, im := range iface.Fields().Slice() {
|
for _, im := range iface.AllMethods().Slice() {
|
||||||
if im.Broke() {
|
if im.Broke() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -806,7 +818,13 @@ func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool)
|
||||||
|
|
||||||
c := 0
|
c := 0
|
||||||
if u.IsStruct() || u.IsInterface() {
|
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 f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
|
||||||
if save != nil {
|
if save != nil {
|
||||||
*save = f
|
*save = f
|
||||||
|
|
|
||||||
|
|
@ -1103,7 +1103,7 @@ func typecheckMethodExpr(n *ir.SelectorExpr) (res ir.Node) {
|
||||||
// Compute the method set for t.
|
// Compute the method set for t.
|
||||||
var ms *types.Fields
|
var ms *types.Fields
|
||||||
if t.IsInterface() {
|
if t.IsInterface() {
|
||||||
ms = t.Fields()
|
ms = t.AllMethods()
|
||||||
} else {
|
} else {
|
||||||
mt := types.ReceiverBaseType(t)
|
mt := types.ReceiverBaseType(t)
|
||||||
if mt == nil {
|
if mt == nil {
|
||||||
|
|
@ -1170,8 +1170,10 @@ func Lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field {
|
||||||
|
|
||||||
types.CalcSize(t)
|
types.CalcSize(t)
|
||||||
var f1 *types.Field
|
var f1 *types.Field
|
||||||
if t.IsStruct() || t.IsInterface() {
|
if t.IsStruct() {
|
||||||
f1 = Lookdot1(n, s, t, t.Fields(), dostrcmp)
|
f1 = Lookdot1(n, s, t, t.Fields(), dostrcmp)
|
||||||
|
} else if t.IsInterface() {
|
||||||
|
f1 = Lookdot1(n, s, t, t.AllMethods(), dostrcmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var f2 *types.Field
|
var f2 *types.Field
|
||||||
|
|
|
||||||
|
|
@ -442,7 +442,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.WriteString("interface {")
|
b.WriteString("interface {")
|
||||||
for i, f := range t.Fields().Slice() {
|
for i, f := range t.AllMethods().Slice() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
b.WriteByte(';')
|
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)
|
tconv2(b, f.Type, 'S', mode, visited)
|
||||||
}
|
}
|
||||||
if t.NumFields() != 0 {
|
if t.AllMethods().Len() != 0 {
|
||||||
b.WriteByte(' ')
|
b.WriteByte(' ')
|
||||||
}
|
}
|
||||||
b.WriteByte('}')
|
b.WriteByte('}')
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,11 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case TINTER:
|
case TINTER:
|
||||||
if t1.NumFields() != t2.NumFields() {
|
if t1.AllMethods().Len() != t2.AllMethods().Len() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i, f1 := range t1.FieldSlice() {
|
for i, f1 := range t1.AllMethods().Slice() {
|
||||||
f2 := t2.Field(i)
|
f2 := t2.AllMethods().Index(i)
|
||||||
if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
|
if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ func expandiface(t *Type) {
|
||||||
// Embedded interface: duplicate all methods
|
// Embedded interface: duplicate all methods
|
||||||
// (including broken ones, if any) and add to t's
|
// (including broken ones, if any) and add to t's
|
||||||
// method set.
|
// 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.
|
// Use m.Pos rather than t1.Pos to preserve embedding position.
|
||||||
f := NewField(m.Pos, t1.Sym, t1.Type)
|
f := NewField(m.Pos, t1.Sym, t1.Type)
|
||||||
addMethod(f, false)
|
addMethod(f, false)
|
||||||
|
|
@ -135,9 +135,7 @@ func expandiface(t *Type) {
|
||||||
m.Offset = int64(i) * int64(PtrSize)
|
m.Offset = int64(i) * int64(PtrSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access fields directly to avoid recursively calling CalcSize
|
t.SetAllMethods(methods)
|
||||||
// within Type.Fields().
|
|
||||||
t.Extra.(*Interface).Fields.Set(methods)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 {
|
func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) {
|
||||||
{Forward{}, 20, 32},
|
{Forward{}, 20, 32},
|
||||||
{Func{}, 28, 48},
|
{Func{}, 28, 48},
|
||||||
{Struct{}, 16, 32},
|
{Struct{}, 16, 32},
|
||||||
{Interface{}, 8, 16},
|
{Interface{}, 4, 8},
|
||||||
{Chan{}, 8, 16},
|
{Chan{}, 8, 16},
|
||||||
{Array{}, 12, 16},
|
{Array{}, 12, 16},
|
||||||
{FuncArgs{}, 4, 8},
|
{FuncArgs{}, 4, 8},
|
||||||
|
|
|
||||||
|
|
@ -368,8 +368,7 @@ func (t *Type) StructType() *Struct {
|
||||||
|
|
||||||
// Interface contains Type fields specific to interface types.
|
// Interface contains Type fields specific to interface types.
|
||||||
type Interface struct {
|
type Interface struct {
|
||||||
Fields Fields
|
pkg *Pkg
|
||||||
pkg *Pkg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ptr contains Type fields specific to pointer types.
|
// 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
|
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 {
|
func (t *Type) Methods() *Fields {
|
||||||
// TODO(mdempsky): Validate t?
|
|
||||||
return &t.methods
|
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 {
|
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
|
return &t.allMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Fields() *Fields {
|
// SetAllMethods sets the set of all methods (including embedding) for type t.
|
||||||
switch t.kind {
|
// Use this method instead of t.AllMethods().Set(), which might call CalcSize() on
|
||||||
case TSTRUCT:
|
// an uninitialized interface type.
|
||||||
return &t.Extra.(*Struct).fields
|
func (t *Type) SetAllMethods(fs []*Field) {
|
||||||
case TINTER:
|
t.allMethods.Set(fs)
|
||||||
CalcSize(t)
|
|
||||||
return &t.Extra.(*Interface).Fields
|
|
||||||
}
|
|
||||||
base.Fatalf("Fields: type %v does not have fields", t)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
func (t *Type) Field(i int) *Field {
|
||||||
return t.Fields().Slice()[i]
|
return t.Fields().Slice()[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldSlice returns a slice of containing all fields/methods of
|
// FieldSlice returns a slice of containing all fields of
|
||||||
// struct/interface type t.
|
// a struct type t.
|
||||||
func (t *Type) FieldSlice() []*Field {
|
func (t *Type) FieldSlice() []*Field {
|
||||||
return t.Fields().Slice()
|
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) {
|
func (t *Type) SetFields(fields []*Field) {
|
||||||
// If we've calculated the width of t before,
|
// If we've calculated the width of t before,
|
||||||
// then some other type such as a function signature
|
// then some other type such as a function signature
|
||||||
|
|
@ -981,6 +989,7 @@ func (t *Type) SetFields(fields []*Field) {
|
||||||
t.Fields().Set(fields)
|
t.Fields().Set(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetInterface sets the base methods of an interface type t.
|
||||||
func (t *Type) SetInterface(methods []*Field) {
|
func (t *Type) SetInterface(methods []*Field) {
|
||||||
t.wantEtype(TINTER)
|
t.wantEtype(TINTER)
|
||||||
t.Methods().Set(methods)
|
t.Methods().Set(methods)
|
||||||
|
|
@ -1231,8 +1240,8 @@ func (t *Type) cmp(x *Type) Cmp {
|
||||||
return CMPeq
|
return CMPeq
|
||||||
|
|
||||||
case TINTER:
|
case TINTER:
|
||||||
tfs := t.FieldSlice()
|
tfs := t.AllMethods().Slice()
|
||||||
xfs := x.FieldSlice()
|
xfs := x.AllMethods().Slice()
|
||||||
for i := 0; i < len(tfs) && i < len(xfs); i++ {
|
for i := 0; i < len(tfs) && i < len(xfs); i++ {
|
||||||
t1, x1 := tfs[i], xfs[i]
|
t1, x1 := tfs[i], xfs[i]
|
||||||
if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
|
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.
|
// IsEmptyInterface reports whether t is an empty interface type.
|
||||||
func (t *Type) IsEmptyInterface() bool {
|
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.
|
// IsScalar reports whether 't' is a scalar Go type, e.g.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue