From f1f3ca7e062d76ebd55b86ca1266bf5a2b154d56 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Wed, 9 Sep 2020 13:44:04 +0200 Subject: [PATCH] fix: handle interface fields in literal composite structs Struct fields of type interface must be converted in wrapper values to be reachable by the runtime. Call genInterfaceWrapper on such values. Fixes #832. --- _test/cli4.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ _test/cli5.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ interp/run.go | 13 +++++++++++-- 3 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 _test/cli4.go create mode 100644 _test/cli5.go diff --git a/_test/cli4.go b/_test/cli4.go new file mode 100644 index 000000000..147b63c3e --- /dev/null +++ b/_test/cli4.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "net/http/httptest" +) + +type mw1 struct { + next http.Handler +} + +func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) { + m.next.ServeHTTP(rw, rq) +} + +type mw0 struct{} + +func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Welcome to my website!") +} + +func main() { + m0 := &mw0{} + m1 := &mw1{m0} + + mux := http.NewServeMux() + mux.HandleFunc("/", m1.ServeHTTP) + + server := httptest.NewServer(mux) + defer server.Close() + + client(server.URL) +} + +func client(uri string) { + resp, err := http.Get(uri) + if err != nil { + log.Fatal(err) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(body)) +} + +// Output: +// Welcome to my website! diff --git a/_test/cli5.go b/_test/cli5.go new file mode 100644 index 000000000..a2e1787c9 --- /dev/null +++ b/_test/cli5.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "net/http/httptest" +) + +type mw1 struct { + next http.Handler +} + +func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) { + m.next.ServeHTTP(rw, rq) +} + +type mw0 struct{} + +func (m *mw0) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Welcome to my website!") +} + +func main() { + m0 := &mw0{} + m1 := &mw1{next: m0} + + mux := http.NewServeMux() + mux.HandleFunc("/", m1.ServeHTTP) + + server := httptest.NewServer(mux) + defer server.Close() + + client(server.URL) +} + +func client(uri string) { + resp, err := http.Get(uri) + if err != nil { + log.Fatal(err) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(body)) +} + +// Output: +// Welcome to my website! diff --git a/interp/run.go b/interp/run.go index ca2c36dc1..07bdb813c 100644 --- a/interp/run.go +++ b/interp/run.go @@ -2078,9 +2078,16 @@ func doCompositeLit(n *node, hasType bool) { values := make([]func(*frame) reflect.Value, len(child)) for i, c := range child { convertLiteralValue(c, typ.field[i].typ.TypeOf()) - if c.typ.cat == funcT { + switch { + case c.typ.cat == funcT: values[i] = genFunctionWrapper(c) - } else { + case isArray(c.typ) && c.typ.val != nil && c.typ.val.cat == interfaceT: + values[i] = genValueInterfaceArray(c) + case isRecursiveType(typ.field[i].typ, typ.field[i].typ.rtype): + values[i] = genValueRecursiveInterface(c, typ.field[i].typ.rtype) + case isInterface(typ.field[i].typ): + values[i] = genInterfaceWrapper(c, typ.field[i].typ.rtype) + default: values[i] = genValue(c) } } @@ -2134,6 +2141,8 @@ func doCompositeSparse(n *node, hasType bool) { values[field] = genValueInterfaceArray(c1) case isRecursiveType(typ.field[field].typ, typ.field[field].typ.rtype): values[field] = genValueRecursiveInterface(c1, typ.field[field].typ.rtype) + case isInterface(typ.field[field].typ): + values[field] = genInterfaceWrapper(c1, typ.field[field].typ.rtype) default: values[field] = genValue(c1) }