From 98c2dcd3e5948abf711fc70cf43a2a028228a35c Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Fri, 24 Sep 2021 13:20:12 +0200 Subject: [PATCH] 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. --- interp/run.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/interp/run.go b/interp/run.go index 139cc458..63fc7460 100644 --- a/interp/run.go +++ b/interp/run.go @@ -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