]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: simplify method set computation
authorRobert Griesemer <gri@golang.org>
Sat, 8 Feb 2020 00:01:01 +0000 (16:01 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 2 Mar 2020 22:19:08 +0000 (22:19 +0000)
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>
src/go/types/methodset.go

index aacbb0f82a35a39be383ff30b907dfc22cd5087a..c34d732b7ac36494427b329301397dbb7f848a2c 100644 (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.