]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: fix FieldByNameFunc
authorRobert Griesemer <gri@golang.org>
Tue, 13 Nov 2012 18:45:30 +0000 (10:45 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 13 Nov 2012 18:45:30 +0000 (10:45 -0800)
The existing algorithm did not properly propagate the type
count from one level to the next, and as a consequence it
missed collisions.

Properly propagate multiplicity (count) information to the
next level.

benchmark                old ns/op    new ns/op    delta
BenchmarkFieldByName1          182          180   -1.10%
BenchmarkFieldByName2         6273         6183   -1.43%
BenchmarkFieldByName3        49267        46784   -5.04%

Fixes #4355.

R=rsc
CC=golang-dev
https://golang.org/cl/6821094

src/pkg/reflect/all_test.go
src/pkg/reflect/type.go

index 1cfab81fe52d593d2dbeb45a139b481fa372b274..12cdbe1ca9b9d4ffde45aa586fe3790ab8ad657f 100644 (file)
@@ -1694,6 +1694,20 @@ type S13 struct {
        S8
 }
 
+// The X in S15.S11.S1 and S16.S11.S1 annihilate.
+type S14 struct {
+       S15
+       S16
+}
+
+type S15 struct {
+       S11
+}
+
+type S16 struct {
+       S11
+}
+
 var fieldTests = []FTest{
        {struct{}{}, "", nil, 0},
        {struct{}{}, "Foo", nil, 0},
@@ -1719,6 +1733,7 @@ var fieldTests = []FTest{
        {S5{}, "Y", []int{2, 0, 1}, 0},
        {S10{}, "X", nil, 0},
        {S10{}, "Y", []int{2, 0, 0, 1}, 0},
+       {S14{}, "X", nil, 0},
 }
 
 func TestFieldByIndex(t *testing.T) {
index 0b029d78c21a4b56d3fb74095fef0421cc277276..110141955c20a0092fcfac9d9b9166dc14db4473 100644 (file)
@@ -913,19 +913,22 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
 
                                // Queue embedded struct fields for processing with next level,
                                // but only if we haven't seen a match yet at this level and only
-                               // if the embedded types haven't alredy been queued.
+                               // if the embedded types haven't already been queued.
                                if ok || ntyp == nil || ntyp.Kind() != Struct {
                                        continue
                                }
                                styp := (*structType)(unsafe.Pointer(ntyp))
                                if nextCount[styp] > 0 {
-                                       nextCount[styp]++
+                                       nextCount[styp] = 2 // exact multiple doesn't matter
                                        continue
                                }
                                if nextCount == nil {
                                        nextCount = map[*structType]int{}
                                }
                                nextCount[styp] = 1
+                               if count[t] > 1 {
+                                       nextCount[styp] = 2 // exact multiple doesn't matter
+                               }
                                var index []int
                                index = append(index, scan.index...)
                                index = append(index, i)