Skip to content

Commit

Permalink
interp: improve interface wrappers when used by reflect
Browse files Browse the repository at this point in the history
When an interpreter type implementing an interface is
used by the runtime, the runtime can extract its type
and create new values using reflect, and call methods
on it. The problem is that there will be no interpreted
method counterpart in this case, which makes wrapper panic.

Allow the String() method wrapper to always succeed and
return an empty string if no interpreted method is present.

This allows scripts to define custom flag.Value types on
which the runtime internally instantiates values using
reflect (see isZeroValue in Go src/flag/flag.go).

This workaround could be generalized to all wrappers if
necessary. At this moment, it is convenient to keep the
default behavior of expecting instantiated interpreter
methods, in order to catch interpreter bugs related to
interfaces.

Fixes #1276.
  • Loading branch information
mvertes authored Oct 8, 2021
1 parent d3bbe01 commit e56db3b
Show file tree
Hide file tree
Showing 181 changed files with 3,244 additions and 1,042 deletions.
24 changes: 24 additions & 0 deletions _test/issue-1276.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"flag"
)

type customFlag struct{}

func (cf customFlag) String() string {
return "custom flag"
}

func (cf customFlag) Set(string) error {
return nil
}

func main() {
flag.Var(customFlag{}, "cf", "custom flag")
flag.Parse()
println("Hello, playground")
}

// Output:
// Hello, playground
9 changes: 8 additions & 1 deletion extract/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ func init() {
{{end}}
}
{{range $m := $value.Method -}}
func (W {{$value.Name}}) {{$m.Name}}{{$m.Param}} {{$m.Result}} { {{$m.Ret}} W.W{{$m.Name}}{{$m.Arg}} }
func (W {{$value.Name}}) {{$m.Name}}{{$m.Param}} {{$m.Result}} {
{{- if eq $m.Name "String"}}
if W.WString == nil {
return ""
}
{{end -}}
{{$m.Ret}} W.W{{$m.Name}}{{$m.Arg}}
}
{{end}}
{{end}}
`
Expand Down
1 change: 1 addition & 0 deletions interp/interp_consistent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
file.Name() == "init1.go" || // expect error
file.Name() == "io0.go" || // use random number
file.Name() == "issue-1093.go" || // expect error
file.Name() == "issue-1276.go" || // expect error
file.Name() == "op1.go" || // expect error
file.Name() == "op7.go" || // expect error
file.Name() == "op9.go" || // expect error
Expand Down
4 changes: 4 additions & 0 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,10 @@ func genFunctionWrapper(n *node) func(*frame) reflect.Value {

// Copy function input arguments in local frame.
for i, arg := range in {
if i >= len(d) {
// In case of unused arg, there may be not even a frame entry allocated, just skip.
break
}
typ := def.typ.arg[i]
switch {
case isEmptyInterface(typ):
Expand Down
12 changes: 9 additions & 3 deletions stdlib/go1_16_compress_flate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion stdlib/go1_16_compress_zlib.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 15 additions & 5 deletions stdlib/go1_16_container_heap.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions stdlib/go1_16_context.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions stdlib/go1_16_crypto.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 24 additions & 8 deletions stdlib/go1_16_crypto_cipher.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions stdlib/go1_16_crypto_elliptic.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions stdlib/go1_16_database_sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e56db3b

Please sign in to comment.