From 274eecdf1821067a06b48566ea6126c20cb9c717 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 19 Jan 2021 19:32:05 +0100 Subject: [PATCH] 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. --- _test/struct59.go | 41 +++++++++++++++++++++++++++++++++++++++++ interp/type.go | 7 ++++--- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 _test/struct59.go diff --git a/_test/struct59.go b/_test/struct59.go new file mode 100644 index 000000000..52f85e408 --- /dev/null +++ b/_test/struct59.go @@ -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[]} diff --git a/interp/type.go b/interp/type.go index 6fde115d8..2cd2eff00 100644 --- a/interp/type.go +++ b/interp/type.go @@ -1414,7 +1414,7 @@ func (t *itype) refType(defined map[string]*itype, wrapRecursive bool) reflect.T t.rtype = reflect.TypeOf(new(error)).Elem() case funcT: if t.name != "" { - defined[name] = t + defined[name] = t // TODO(marc): make sure that key is name and not t.name. } variadic := false 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)) case structT: 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 } - defined[name] = t + defined[t.name] = t } var fields []reflect.StructField // TODO(mpl): make Anonymous work for recursive types too. Maybe not worth the