diff --git a/_test/cli7.go b/_test/cli7.go new file mode 100644 index 000000000..fbe2f19dc --- /dev/null +++ b/_test/cli7.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "io" + "log" + "net/http" + "net/http/httptest" +) + +type T struct { + http.ResponseWriter +} + +type mw1 struct { +} + +var obj = map[string]interface{}{} + +func (m *mw1) ServeHTTP(rw http.ResponseWriter, rq *http.Request) { + t := &T{ + ResponseWriter: rw, + } + x := t.Header() + i := obj["m1"].(*mw1) + fmt.Fprint(rw, "Welcome to my website!", x, i) +} + +func main() { + m1 := &mw1{} + + obj["m1"] = m1 + + 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 := io.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(body)) +} + +// Output: +// Welcome to my website!map[] &{} diff --git a/_test/type24.go b/_test/type24.go index 79449d666..7bcb94ba3 100644 --- a/_test/type24.go +++ b/_test/type24.go @@ -43,6 +43,6 @@ func assertValue() { } // Output: -// interface conversion: interface {} is int, not string -// interface conversion: interface {} is nil, not string -// interface conversion: *httptest.ResponseRecorder is not http.Pusher: missing method Push +// 22:10: interface conversion: interface {} is int, not string +// 32:10: interface conversion: interface {} is nil, not string +// 42:10: interface conversion: *httptest.ResponseRecorder is not http.Pusher: missing method Push diff --git a/interp/interp_consistent_test.go b/interp/interp_consistent_test.go index 0187b215b..d1c430c88 100644 --- a/interp/interp_consistent_test.go +++ b/interp/interp_consistent_test.go @@ -109,6 +109,7 @@ func TestInterpConsistencyBuild(t *testing.T) { file.Name() == "range9.go" || // expect error file.Name() == "unsafe6.go" || // needs go.mod to be 1.17 file.Name() == "unsafe7.go" || // needs go.mod to be 1.17 + file.Name() == "type24.go" || // expect error file.Name() == "type27.go" || // expect error file.Name() == "type28.go" || // expect error file.Name() == "type29.go" || // expect error diff --git a/interp/interp_file_test.go b/interp/interp_file_test.go index f29b117df..d9f1e208f 100644 --- a/interp/interp_file_test.go +++ b/interp/interp_file_test.go @@ -7,6 +7,7 @@ import ( "go/token" "os" "path/filepath" + "regexp" "strings" "testing" @@ -76,7 +77,9 @@ func runCheck(t *testing.T, p string) { t.Fatal(err) } - if res := strings.TrimSpace(stdout.String()); res != wanted { + // Remove path in output, to have results independent of location. + re := regexp.MustCompile(p + ":") + if res := re.ReplaceAllString(strings.TrimSpace(stdout.String()), ""); res != wanted { t.Errorf("\ngot: %q,\nwant: %q", res, wanted) } } diff --git a/interp/run.go b/interp/run.go index 7660d1df0..c592b606d 100644 --- a/interp/run.go +++ b/interp/run.go @@ -401,7 +401,7 @@ func typeAssert(n *node, withResult, withOk bool) { ok = v.IsValid() if !ok { if !withOk { - panic(fmt.Sprintf("interface conversion: interface {} is nil, not %s", rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is nil, not %s", rtype.String())) } return next } @@ -409,7 +409,7 @@ func typeAssert(n *node, withResult, withOk bool) { if !ok { if !withOk { method := firstMissingMethod(leftType, rtype) - panic(fmt.Sprintf("interface conversion: %s is not %s: missing method %s", leftType.String(), rtype.String(), method)) + panic(n.cfgErrorf("interface conversion: %s is not %s: missing method %s", leftType.String(), rtype.String(), method)) } return next } @@ -430,14 +430,18 @@ func typeAssert(n *node, withResult, withOk bool) { concrete := val.Interface() ctyp := reflect.TypeOf(concrete) + if vv, ok := concrete.(valueInterface); ok { + ctyp = vv.value.Type() + concrete = vv.value.Interface() + } ok = canAssertTypes(ctyp, rtype) if !ok { if !withOk { // TODO(mpl): think about whether this should ever happen. if ctyp == nil { - panic(fmt.Sprintf("interface conversion: interface {} is nil, not %s", rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is nil, not %s", rtype.String())) } - panic(fmt.Sprintf("interface conversion: interface {} is %s, not %s", ctyp.String(), rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is %s, not %s", ctyp.String(), rtype.String())) } return next } @@ -462,7 +466,7 @@ func typeAssert(n *node, withResult, withOk bool) { } if !ok { if !withOk { - panic(fmt.Sprintf("interface conversion: interface {} is nil, not %s", rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is nil, not %s", rtype.String())) } return next } @@ -475,7 +479,7 @@ func typeAssert(n *node, withResult, withOk bool) { if !ok { if !withOk { method := firstMissingMethod(v.Type(), rtype) - panic(fmt.Sprintf("interface conversion: %s is not %s: missing method %s", v.Type().String(), rtype.String(), method)) + panic(n.cfgErrorf("interface conversion: %s is not %s: missing method %s", v.Type().String(), rtype.String(), method)) } return next } @@ -495,7 +499,7 @@ func typeAssert(n *node, withResult, withOk bool) { if !ok || !v.value.IsValid() { ok = false if !withOk { - panic(fmt.Sprintf("interface conversion: interface {} is nil, not %s", rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is nil, not %s", rtype.String())) } return next } @@ -503,7 +507,7 @@ func typeAssert(n *node, withResult, withOk bool) { ok = canAssertTypes(v.value.Type(), rtype) if !ok { if !withOk { - panic(fmt.Sprintf("interface conversion: interface {} is %s, not %s", v.value.Type().String(), rtype.String())) + panic(n.cfgErrorf("interface conversion: interface {} is %s, not %s", v.value.Type().String(), rtype.String())) } return next } @@ -567,7 +571,7 @@ func convert(n *node) { n.exec = func(f *frame) bltn { n, ok := value(f).Interface().(*node) if !ok || !n.typ.convertibleTo(c.typ) { - panic("cannot convert") + panic(n.cfgErrorf("cannot convert to %s", c.typ.id())) } n1 := *n n1.typ = c.typ @@ -3611,7 +3615,7 @@ func convertConstantValue(n *node) { case constant.Int: i, x := constant.Int64Val(c) if !x { - panic(fmt.Sprintf("constant %s overflows int64", c.ExactString())) + panic(n.cfgErrorf("constant %s overflows int64", c.ExactString())) } v = reflect.ValueOf(int(i)) case constant.Float: