Skip to content

Commit

Permalink
fix: emulate struct by interface{} only for recursive struct types
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Dec 16, 2019
1 parent 7a0c09f commit 4f93be7
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 2 deletions.
19 changes: 19 additions & 0 deletions _test/struct29.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

type T1 struct {
A []T2
B []T2
}

type T2 struct {
name string
}

var t = T1{}

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

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

type T1 struct {
A []T2
M map[uint64]T2
}

type T2 struct {
name string
}

var t = T1{}

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

// Output:
// ok
1 change: 1 addition & 0 deletions interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func (interp *Interpreter) gta(root *node, rpath string) ([]*node, error) {
case defineStmt:
var atyp *itype
if n.nleft+n.nright < len(n.child) {
// Type is declared explicitly in the assign expression.
if atyp, err = nodeType(interp, sc, n.child[n.nleft]); err != nil {
return false
}
Expand Down
2 changes: 1 addition & 1 deletion interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func isRecursiveStruct(t *itype, rtype reflect.Type) bool {
if t.cat == structT && rtype.Kind() == reflect.Interface {
return true
}
if t.cat == ptrT {
if t.cat == ptrT && t.rtype != nil {
return isRecursiveStruct(t.val, t.rtype.Elem())
}
return false
Expand Down
4 changes: 3 additions & 1 deletion interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,9 @@ func (t *itype) refType(defined map[string]bool) reflect.Type {
panic(err)
}
}
if t.val != nil && defined[t.val.name] {
if t.val != nil && defined[t.val.name] && !t.val.incomplete && t.val.rtype == nil {
// Replace reference to self (direct or indirect) by an interface{} to handle
// recursive types with reflect.
t.val.rtype = interf
}
switch t.cat {
Expand Down

0 comments on commit 4f93be7

Please sign in to comment.