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.
This commit is contained in:
@@ -364,12 +364,25 @@ func structOf(t *itype, fields []structField, opts ...itypeOption) *itype {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeType returns a type definition for the corresponding AST subtree.
|
// seenNode determines if a node has been seen.
|
||||||
func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
|
//
|
||||||
return nodeType2(interp, sc, n, map[*node]bool{})
|
// seenNode treats the slice of nodes as the path traveled down a node
|
||||||
|
// tree.
|
||||||
|
func seenNode(ns []*node, n *node) bool {
|
||||||
|
for _, nn := range ns {
|
||||||
|
if nn == n {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t *itype, err error) {
|
// nodeType returns a type definition for the corresponding AST subtree.
|
||||||
|
func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
|
||||||
|
return nodeType2(interp, sc, n, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype, err error) {
|
||||||
if n.typ != nil && !n.typ.incomplete {
|
if n.typ != nil && !n.typ.incomplete {
|
||||||
return n.typ, nil
|
return n.typ, nil
|
||||||
}
|
}
|
||||||
@@ -379,14 +392,15 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t
|
|||||||
if sym.typ.isComplete() {
|
if sym.typ.isComplete() {
|
||||||
return sym.typ, nil
|
return sym.typ, nil
|
||||||
}
|
}
|
||||||
if seen[n] {
|
if seenNode(seen, n) {
|
||||||
// TODO (marc): find a better way to distinguish recursive vs incomplete types.
|
// We have seen this node in our tree, so it must be recursive.
|
||||||
sym.typ.incomplete = false
|
sym.typ.incomplete = false
|
||||||
return sym.typ, nil
|
return sym.typ, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seen[n] = true
|
seen = append(seen, n)
|
||||||
|
defer func() { seen = seen[:len(seen)-1] }()
|
||||||
|
|
||||||
switch n.kind {
|
switch n.kind {
|
||||||
case addressExpr, starExpr:
|
case addressExpr, starExpr:
|
||||||
|
|||||||
Reference in New Issue
Block a user