interp: fix type recursivity detection
Fix the logic to detect recursive struct types, which was giving a false positive. We now use the local type name as key in tracker map. A non-regression test case is included (_test/struct49.go). This completes #1008.
This commit is contained in:
41
_test/struct59.go
Normal file
41
_test/struct59.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type A struct {
|
||||||
|
B map[string]*B
|
||||||
|
C map[string]*C
|
||||||
|
}
|
||||||
|
|
||||||
|
type C struct {
|
||||||
|
D *D
|
||||||
|
E *E
|
||||||
|
}
|
||||||
|
|
||||||
|
type D struct {
|
||||||
|
F *F
|
||||||
|
G []G
|
||||||
|
}
|
||||||
|
|
||||||
|
type E struct {
|
||||||
|
H []H
|
||||||
|
F *F
|
||||||
|
}
|
||||||
|
|
||||||
|
type B struct{}
|
||||||
|
type F struct{}
|
||||||
|
type G struct{}
|
||||||
|
type H struct{}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conf := &A{
|
||||||
|
B: make(map[string]*B),
|
||||||
|
C: make(map[string]*C),
|
||||||
|
}
|
||||||
|
fmt.Println(conf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// &{map[] map[]}
|
||||||
@@ -1414,7 +1414,7 @@ func (t *itype) refType(defined map[string]*itype, wrapRecursive bool) reflect.T
|
|||||||
t.rtype = reflect.TypeOf(new(error)).Elem()
|
t.rtype = reflect.TypeOf(new(error)).Elem()
|
||||||
case funcT:
|
case funcT:
|
||||||
if t.name != "" {
|
if t.name != "" {
|
||||||
defined[name] = t
|
defined[name] = t // TODO(marc): make sure that key is name and not t.name.
|
||||||
}
|
}
|
||||||
variadic := false
|
variadic := false
|
||||||
in := make([]reflect.Type, len(t.arg))
|
in := make([]reflect.Type, len(t.arg))
|
||||||
@@ -1435,10 +1435,11 @@ func (t *itype) refType(defined map[string]*itype, wrapRecursive bool) reflect.T
|
|||||||
t.rtype = reflect.PtrTo(t.val.refType(defined, wrapRecursive))
|
t.rtype = reflect.PtrTo(t.val.refType(defined, wrapRecursive))
|
||||||
case structT:
|
case structT:
|
||||||
if t.name != "" {
|
if t.name != "" {
|
||||||
if defined[name] != nil {
|
// Check against local t.name and not name to catch recursive type definitions.
|
||||||
|
if defined[t.name] != nil {
|
||||||
recursive = true
|
recursive = true
|
||||||
}
|
}
|
||||||
defined[name] = t
|
defined[t.name] = t
|
||||||
}
|
}
|
||||||
var fields []reflect.StructField
|
var fields []reflect.StructField
|
||||||
// TODO(mpl): make Anonymous work for recursive types too. Maybe not worth the
|
// TODO(mpl): make Anonymous work for recursive types too. Maybe not worth the
|
||||||
|
|||||||
Reference in New Issue
Block a user