Skip to content

Commit

Permalink
fix: incomplete type analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes committed Apr 3, 2020
1 parent b20ad3a commit b0053c8
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
22 changes: 22 additions & 0 deletions _test/struct39.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

type T struct {
t *T1
y *xxx
}

type T1 struct {
T
}

var x = &T1{}
var t = &T{}

type xxx struct{}

func main() {
println("ok")
}

// Output:
// ok
23 changes: 23 additions & 0 deletions _test/struct40.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

type T struct {
t *T1
y *xxx
}

type T1 struct {
T
}

func f(t *T) { println("in f") }

var x = &T1{}

type xxx struct{}

func main() {
println("ok")
}

// Output:
// ok
8 changes: 4 additions & 4 deletions interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
}
val = src.rval
}
if typ.incomplete {
if !typ.isComplete() {
// Come back when type is known.
revisit = append(revisit, n)
return false
Expand Down Expand Up @@ -94,7 +94,7 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
if n.typ, err = nodeType(interp, sc, n.child[l]); err != nil {
return false
}
if n.typ.incomplete {
if !n.typ.isComplete() {
// Come back when type is known.
revisit = append(revisit, n)
return false
Expand Down Expand Up @@ -139,7 +139,7 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
// Add a function symbol in the package name space
sc.sym[n.child[1].ident] = &symbol{kind: funcSym, typ: n.typ, node: n, index: -1}
}
if n.typ.incomplete {
if !n.typ.isComplete() {
revisit = append(revisit, n)
}
return false
Expand Down Expand Up @@ -206,7 +206,7 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
n.typ.method = append(n.typ.method, sc.sym[typeName].typ.method...)
}
sc.sym[typeName].typ = n.typ
if n.typ.incomplete {
if !n.typ.isComplete() {
revisit = append(revisit, n)
}
return false
Expand Down
37 changes: 37 additions & 0 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,43 @@ func (t *itype) finalize() (*itype, error) {
return t, err
}

// isComplete returns true if type definition is complete.
func (t *itype) isComplete() bool { return isComplete(t, map[string]bool{}) }

func isComplete(t *itype, visited map[string]bool) bool {
if t.incomplete {
return false
}
if visited[t.name] {
return !t.incomplete
}
if t.name != "" {
visited[t.name] = true
}
switch t.cat {
case aliasT, arrayT, chanT, ptrT:
return isComplete(t.val, visited)
case funcT:
complete := true
for _, a := range t.arg {
complete = complete && isComplete(a, visited)
}
for _, a := range t.ret {
complete = complete && isComplete(a, visited)
}
return complete
case interfaceT, structT:
complete := true
for _, f := range t.field {
complete = complete && isComplete(f.typ, visited)
}
return complete
case nilT:
return false
}
return true
}

// Equals returns true if the given type is identical to the receiver one.
func (t *itype) equals(o *itype) bool {
switch ti, oi := isInterface(t), isInterface(o); {
Expand Down

0 comments on commit b0053c8

Please sign in to comment.