mirror of
https://github.com/golang/go.git
synced 2026-02-06 09:50:02 +00:00
go/types, types2: in resolveUnderlying, only compute path when needed
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>
This commit is contained in:
parent
4bdb55b5b8
commit
5a42af7f6c
2 changed files with 22 additions and 10 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue