interp: fix interface wrapper for struct types

This change fixes a regression introduced by PR #1192 in a program using
https://github.com/NYTimes/gziphandler which defines several types
implementing stdlib interfaces. We do not implement a wrapper
if we see that a type already implements an interface, except that
it can be falsly reported by reflect in case of a struct with
embedded interface field. We need to force the wrapper generation
in this case.
The problem occurs only for wrappers on struct, not on pointers or
other indirection types.
This commit is contained in:
Marc Vertes
2021-09-24 13:20:12 +02:00
committed by GitHub
parent 808f0bde9d
commit 98c2dcd3e5

View File

@@ -1006,9 +1006,14 @@ func genInterfaceWrapper(n *node, typ reflect.Type) func(*frame) reflect.Value {
if typ == nil || typ.Kind() != reflect.Interface || typ.NumMethod() == 0 || n.typ.cat == valueT {
return value
}
nt := n.typ.frameType()
if nt != nil && nt.Implements(typ) {
return value
tc := n.typ.cat
if tc != structT {
// Always force wrapper generation for struct types, as they may contain
// embedded interface fields which require wrapping, even if reported as
// implementing typ by reflect.
if nt := n.typ.frameType(); nt != nil && nt.Implements(typ) {
return value
}
}
mn := typ.NumMethod()
names := make([]string, mn)
@@ -1026,7 +1031,7 @@ func genInterfaceWrapper(n *node, typ reflect.Type) func(*frame) reflect.Value {
return func(f *frame) reflect.Value {
v := value(f)
if v.Type().Implements(typ) {
if tc != structT && v.Type().Implements(typ) {
return v
}
vv := v