Skip to content

Commit

Permalink
interp: create interpreter interface value with new
Browse files Browse the repository at this point in the history
In that case, the interface must be wrapped in an valueInterface
at creation.

With that fix, it is now possible to import
github.com/google/go-querystring/query. Not tested beyond that.

Fixes #1123.
  • Loading branch information
mvertes committed Jun 13, 2022
1 parent 6933ba2 commit eaeb445
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
2 changes: 1 addition & 1 deletion interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
// retry with the filename, in case ident is a package name.
sym, level, found = sc.lookup(filepath.Join(n.ident, baseName))
if !found {
err = n.cfgErrorf("undefined: %s %d", n.ident, n.index)
err = n.cfgErrorf("undefined: %s", n.ident)
break
}
}
Expand Down
23 changes: 23 additions & 0 deletions interp/interp_eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,29 @@ func TestEvalBinCall(t *testing.T) {
})
}

func TestEvalReflect(t *testing.T) {
i := interp.New(interp.Options{})
if err := i.Use(stdlib.Symbols); err != nil {
t.Fatal(err)
}
if _, err := i.Eval(`
import (
"net/url"
"reflect"
)
type Encoder interface {
EncodeValues(key string, v *url.Values) error
}
`); err != nil {
t.Fatal(err)
}

runTests(t, i, []testCase{
{src: "reflect.TypeOf(new(Encoder)).Elem()", res: "interp.valueInterface"},
})
}

func TestEvalMissingSymbol(t *testing.T) {
defer func() {
r := recover()
Expand Down
13 changes: 11 additions & 2 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3303,11 +3303,20 @@ func _len(n *node) {

func _new(n *node) {
next := getExec(n.tnext)
typ := n.child[1].typ.TypeOf()
t1 := n.child[1].typ
typ := t1.TypeOf()
dest := genValueOutput(n, reflect.PtrTo(typ))

if isInterfaceSrc(t1) && (!isEmptyInterface(t1) || len(t1.method) > 0) {
typ = zeroInterfaceValue().Type()
}

n.exec = func(f *frame) bltn {
dest(f).Set(reflect.New(typ))
v := reflect.New(typ)
if vi, ok := v.Interface().(*valueInterface); ok {
vi.node = n
}
dest(f).Set(v)
return next
}
}
Expand Down

0 comments on commit eaeb445

Please sign in to comment.