From d6ad13aceaf91765d10e14b585b264a2633b791d Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Thu, 13 Apr 2023 18:16:05 +0200 Subject: [PATCH] interp: improve handling of embedded fields with binary methods Only structures with one embedded field can be marked anonymous, due to golang/go#15924. Also check only that the method is defined, do not verify its complete signature, as the receiver may or not be defined in the arguments of the method. Fixes #1537. --- _test/method40.go | 32 ++++++++++++++++++++++++++++++++ interp/type.go | 17 +++++++++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 _test/method40.go diff --git a/_test/method40.go b/_test/method40.go new file mode 100644 index 000000000..0f6692e7d --- /dev/null +++ b/_test/method40.go @@ -0,0 +1,32 @@ +package main + +import ( + "bytes" + "io" +) + +type TMemoryBuffer struct { + *bytes.Buffer + size int +} + +func newTMemoryBuffer() *TMemoryBuffer { + return &TMemoryBuffer{} +} + +var globalMemoryBuffer = newTMemoryBuffer() + +type TTransport interface { + io.ReadWriter +} + +func check(t TTransport) { + println("ok") +} + +func main() { + check(globalMemoryBuffer) +} + +// Output: +// ok diff --git a/interp/type.go b/interp/type.go index 4c28973f2..77fc4b3be 100644 --- a/interp/type.go +++ b/interp/type.go @@ -1544,8 +1544,11 @@ type methodSet map[string]string // Contains returns true if the method set m contains the method set n. func (m methodSet) contains(n methodSet) bool { - for k, v := range n { - if m[k] != v { + for k := range n { + // Only check the presence of method, not its complete signature, + // as the receiver may be part of the arguments, which makes a + // robust check complex. + if _, ok := m[k]; !ok { return false } } @@ -2132,8 +2135,14 @@ func (t *itype) refType(ctx *refTypeContext) reflect.Type { var fields []reflect.StructField for _, f := range t.field { field := reflect.StructField{ - Name: exportName(f.name), Type: f.typ.refType(ctx), - Tag: reflect.StructTag(f.tag), Anonymous: f.embed, + Name: exportName(f.name), + Type: f.typ.refType(ctx), + Tag: reflect.StructTag(f.tag), + } + if len(t.field) == 1 && f.embed { + // Mark the field as embedded (anonymous) only if it is the + // only one, to avoid a panic due to golang/go#15924 issue. + field.Anonymous = true } fields = append(fields, field) // Find any nil type refs that indicates a rebuild is needed on this field.