diff options
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/all_test.go | 86 | ||||
-rw-r--r-- | src/reflect/type.go | 15 |
2 files changed, 69 insertions, 32 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 308cb77a8f..5a5c91b751 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -4686,41 +4686,67 @@ func TestStructOfWithInterface(t *testing.T) { } for i, table := range tests { - rt := StructOf( - []StructField{ - { - Name: table.name, - Anonymous: true, - PkgPath: "", - Type: table.typ, - }, - }, - ) - rv := New(rt).Elem() - rv.Field(0).Set(table.val) + for j := 0; j < 2; j++ { + var fields []StructField + if j == 1 { + fields = append(fields, StructField{ + Name: "Dummy", + PkgPath: "", + Type: TypeOf(int(0)), + }) + } + fields = append(fields, StructField{ + Name: table.name, + Anonymous: true, + PkgPath: "", + Type: table.typ, + }) - if _, ok := rv.Interface().(Iface); ok != table.impl { - if table.impl { - t.Errorf("test-%d: type=%v fails to implement Iface.\n", i, table.typ) - } else { - t.Errorf("test-%d: type=%v should NOT implement Iface\n", i, table.typ) + // We currently do not correctly implement methods + // for anonymous fields other than the first. + // Therefore, for now, we expect those methods + // to not exist. See issues 15924 and 20824. + // When those issues are fixed, this test of panic + // should be removed. + if j == 1 && table.impl { + func() { + defer func() { + if err := recover(); err == nil { + t.Errorf("test-%d-%d did not panic", i, j) + } + }() + _ = StructOf(fields) + }() + continue } - continue - } - if !table.impl { - continue - } + rt := StructOf(fields) + rv := New(rt).Elem() + rv.Field(j).Set(table.val) - v := rv.Interface().(Iface).Get() - if v != want { - t.Errorf("test-%d: x.Get()=%v. want=%v\n", i, v, want) - } + if _, ok := rv.Interface().(Iface); ok != table.impl { + if table.impl { + t.Errorf("test-%d-%d: type=%v fails to implement Iface.\n", i, j, table.typ) + } else { + t.Errorf("test-%d-%d: type=%v should NOT implement Iface\n", i, j, table.typ) + } + continue + } - fct := rv.MethodByName("Get") - out := fct.Call(nil) - if !DeepEqual(out[0].Interface(), want) { - t.Errorf("test-%d: x.Get()=%v. want=%v\n", i, out[0].Interface(), want) + if !table.impl { + continue + } + + v := rv.Interface().(Iface).Get() + if v != want { + t.Errorf("test-%d-%d: x.Get()=%v. want=%v\n", i, j, v, want) + } + + fct := rv.MethodByName("Get") + out := fct.Call(nil) + if !DeepEqual(out[0].Interface(), want) { + t.Errorf("test-%d-%d: x.Get()=%v. want=%v\n", i, j, out[0].Interface(), want) + } } } } diff --git a/src/reflect/type.go b/src/reflect/type.go index 14c16fc832..cbf4f73bf4 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2434,7 +2434,7 @@ func StructOf(fields []StructField) Type { ift := (*interfaceType)(unsafe.Pointer(ft)) for im, m := range ift.methods { if ift.nameOff(m.name).pkgPath() != "" { - // TODO(sbinet) + // TODO(sbinet). Issue 15924. panic("reflect: embedded interface with unexported method(s) not implemented") } @@ -2492,10 +2492,15 @@ func StructOf(fields []StructField) Type { case Ptr: ptr := (*ptrType)(unsafe.Pointer(ft)) if unt := ptr.uncommon(); unt != nil { + if i > 0 && unt.mcount > 0 { + // Issue 15924. + panic("reflect: embedded type with methods not implemented if type is not first field") + } for _, m := range unt.methods() { mname := ptr.nameOff(m.name) if mname.pkgPath() != "" { - // TODO(sbinet) + // TODO(sbinet). + // Issue 15924. panic("reflect: embedded interface with unexported method(s) not implemented") } methods = append(methods, method{ @@ -2511,6 +2516,7 @@ func StructOf(fields []StructField) Type { mname := ptr.nameOff(m.name) if mname.pkgPath() != "" { // TODO(sbinet) + // Issue 15924. panic("reflect: embedded interface with unexported method(s) not implemented") } methods = append(methods, method{ @@ -2523,10 +2529,15 @@ func StructOf(fields []StructField) Type { } default: if unt := ft.uncommon(); unt != nil { + if i > 0 && unt.mcount > 0 { + // Issue 15924. + panic("reflect: embedded type with methods not implemented if type is not first field") + } for _, m := range unt.methods() { mname := ft.nameOff(m.name) if mname.pkgPath() != "" { // TODO(sbinet) + // Issue 15924. panic("reflect: embedded interface with unexported method(s) not implemented") } methods = append(methods, method{ |