Skip to content

Commit 286d6c6

Browse files
authored
interp: handle recursive and incomplete seen types in nodeType
This comes from experiments looking into #1259 where incomplete twice seen types are marked as complete. To mitigate the problem instead of a map of seen types in `nodeType` a slice is used as a cheap way to keep track of our current path through the node tree.
1 parent 84424b5 commit 286d6c6

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

interp/type.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,25 @@ func structOf(t *itype, fields []structField, opts ...itypeOption) *itype {
364364
return t
365365
}
366366

367+
// seenNode determines if a node has been seen.
368+
//
369+
// seenNode treats the slice of nodes as the path traveled down a node
370+
// tree.
371+
func seenNode(ns []*node, n *node) bool {
372+
for _, nn := range ns {
373+
if nn == n {
374+
return true
375+
}
376+
}
377+
return false
378+
}
379+
367380
// nodeType returns a type definition for the corresponding AST subtree.
368381
func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
369-
return nodeType2(interp, sc, n, map[*node]bool{})
382+
return nodeType2(interp, sc, n, nil)
370383
}
371384

372-
func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t *itype, err error) {
385+
func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype, err error) {
373386
if n.typ != nil && !n.typ.incomplete {
374387
return n.typ, nil
375388
}
@@ -379,14 +392,15 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t
379392
if sym.typ.isComplete() {
380393
return sym.typ, nil
381394
}
382-
if seen[n] {
383-
// TODO (marc): find a better way to distinguish recursive vs incomplete types.
395+
if seenNode(seen, n) {
396+
// We have seen this node in our tree, so it must be recursive.
384397
sym.typ.incomplete = false
385398
return sym.typ, nil
386399
}
387400
}
388401
}
389-
seen[n] = true
402+
seen = append(seen, n)
403+
defer func() { seen = seen[:len(seen)-1] }()
390404

391405
switch n.kind {
392406
case addressExpr, starExpr:

0 commit comments

Comments
 (0)