]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: in resolveUnderlying, only compute path when needed
authorRobert Griesemer <gri@google.com>
Mon, 20 Oct 2025 17:25:23 +0000 (10:25 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 22 Oct 2025 15:22:02 +0000 (08:22 -0700)
When following a RHS chain, the (TypeName) Object path is only needed
when there is a cycle (i.e., an error), in which case we can be slow.
Rather than always compute the path, only compute it in the error case.
In the same vain, allocate the seen map lazily, only when needed.

This code could use a test (it doesn't seem to be encountered by our
test suite), but I haven't found a case to provoke the error yet.

Change-Id: Iff6313394442a251adc56580f746928ec13450fd
Reviewed-on: https://go-review.googlesource.com/c/go/+/712321
Auto-Submit: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/named.go
src/go/types/named.go

index 856f33028a41a14cd20451ffe6a29a4cff9f87e5..99e27434840bedadaa6808cb0a79a49da785153a 100644 (file)
@@ -593,9 +593,7 @@ func (n *Named) resolveUnderlying() {
                return
        }
 
-       seen := make(map[*Named]int)
-       var path []Object
-
+       var seen map[*Named]int // allocated lazily
        var u Type
        for rhs := Type(n); u == nil; {
                switch t := rhs.(type) {
@@ -607,9 +605,15 @@ func (n *Named) resolveUnderlying() {
 
                case *Named:
                        if i, ok := seen[t]; ok {
+                               // compute cycle path
+                               path := make([]Object, len(seen))
+                               for t, j := range seen {
+                                       path[j] = t.obj
+                               }
+                               path = path[i:]
                                // Note: This code may only be called during type checking,
                                //       hence n.check != nil.
-                               n.check.cycleError(path[i:], firstInSrc(path[i:]))
+                               n.check.cycleError(path, firstInSrc(path))
                                u = Typ[Invalid]
                                break
                        }
@@ -625,8 +629,10 @@ func (n *Named) resolveUnderlying() {
                                break
                        }
 
+                       if seen == nil {
+                               seen = make(map[*Named]int)
+                       }
                        seen[t] = len(seen)
-                       path = append(path, t.obj)
 
                        assert(t.fromRHS != nil || t.allowNilRHS)
                        rhs = t.fromRHS
index 5c5c837987539cba882209dbfc1ccd8e918bc696..b436d073e6dfa9cfbdb00cb025a7b71d3848269c 100644 (file)
@@ -596,9 +596,7 @@ func (n *Named) resolveUnderlying() {
                return
        }
 
-       seen := make(map[*Named]int)
-       var path []Object
-
+       var seen map[*Named]int // allocated lazily
        var u Type
        for rhs := Type(n); u == nil; {
                switch t := rhs.(type) {
@@ -610,9 +608,15 @@ func (n *Named) resolveUnderlying() {
 
                case *Named:
                        if i, ok := seen[t]; ok {
+                               // compute cycle path
+                               path := make([]Object, len(seen))
+                               for t, j := range seen {
+                                       path[j] = t.obj
+                               }
+                               path = path[i:]
                                // Note: This code may only be called during type checking,
                                //       hence n.check != nil.
-                               n.check.cycleError(path[i:], firstInSrc(path[i:]))
+                               n.check.cycleError(path, firstInSrc(path))
                                u = Typ[Invalid]
                                break
                        }
@@ -628,8 +632,10 @@ func (n *Named) resolveUnderlying() {
                                break
                        }
 
+                       if seen == nil {
+                               seen = make(map[*Named]int)
+                       }
                        seen[t] = len(seen)
-                       path = append(path, t.obj)
 
                        assert(t.fromRHS != nil || t.allowNilRHS)
                        rhs = t.fromRHS