1
0
mirror of https://github.com/golang/go synced 2024-11-27 05:11:22 -07:00

go/types: simplify method set computation

After fixing #37081 we don't need to explicitly keep track of
field collisions in the method set computation anymore; we only
need to know which field (names) exists at each embedding level.
Simplify the code by removing the dedicated fieldSet data type
in favor of a simple string set.

Follow-up on https://golang.org/cl/218617; separate CL to make it
easier to identify a problem with these two changes, should there
be one.

Updates #37081.

Change-Id: I5c259c63c75a148a42d5c3e1e4860e1ffe5631bd
Reviewed-on: https://go-review.googlesource.com/c/go/+/218618
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Robert Griesemer 2020-02-07 16:01:01 -08:00
parent ca3dd1d36b
commit 117297cf42

View File

@ -99,8 +99,8 @@ func NewMethodSet(T Type) *MethodSet {
for len(current) > 0 {
var next []embeddedType // embedded types found at current depth
// field and method sets at current depth, allocated lazily
var fset fieldSet
// field and method sets at current depth, indexed by names (Id's), and allocated lazily
var fset map[string]bool // we only care about the field names
var mset methodSet
for _, e := range current {
@ -131,7 +131,10 @@ func NewMethodSet(T Type) *MethodSet {
switch t := typ.(type) {
case *Struct:
for i, f := range t.fields {
fset = fset.add(f, e.multiples)
if fset == nil {
fset = make(map[string]bool)
}
fset[f.Id()] = true
// Embedded fields are always of the form T or *T where
// T is a type name. If typ appeared multiple times at
@ -156,7 +159,7 @@ func NewMethodSet(T Type) *MethodSet {
for k, m := range mset {
if _, found := base[k]; !found {
// Fields collide with methods of the same name at this depth.
if _, found := fset[k]; found {
if fset[k] {
m = nil // collision
}
if base == nil {
@ -166,9 +169,8 @@ func NewMethodSet(T Type) *MethodSet {
}
}
// Add all fields at this depth as collisions (since they will hide any
// method further down) to base if no entries with matching names exist
// already.
// Add all (remaining) fields at this depth as collisions (since they will
// hide any method further down) if no entries with matching names exist already.
for k := range fset {
if _, found := base[k]; !found {
if base == nil {
@ -205,30 +207,6 @@ func NewMethodSet(T Type) *MethodSet {
return &MethodSet{list}
}
// A fieldSet is a set of fields and name collisions.
// A collision indicates that multiple fields with the
// same unique id appeared.
type fieldSet map[string]*Var // a nil entry indicates a name collision
// Add adds field f to the field set s.
// If multiples is set, f appears multiple times
// and is treated as a collision.
func (s fieldSet) add(f *Var, multiples bool) fieldSet {
if s == nil {
s = make(fieldSet)
}
key := f.Id()
// if f is not in the set, add it
if !multiples {
if _, found := s[key]; !found {
s[key] = f
return s
}
}
s[key] = nil // collision
return s
}
// A methodSet is a set of methods and name collisions.
// A collision indicates that multiple methods with the
// same unique id, or a field with that id appeared.