Skip to content

Commit 155eedb

Browse files
committed
reflect: fix embedded interface field methods
DO NOT SUBMIT INCOMPLETE PATCH Previously, a call to a StructOf method from an embedded interface field would cause a segfault, so fix the behaviour to either succeed in calling the method or, if available method slots have been exhausted, cause a clean panic. Updates golang#38783 Update 2023/09/03: Commit rebased onto current master. However, ·dispatchLabel assumes the old ABI0, which is wrong, causing this patch to not work.
1 parent 0cd473d commit 155eedb

File tree

4 files changed

+1161
-47
lines changed

4 files changed

+1161
-47
lines changed

src/reflect/all_test.go

+168
Original file line numberDiff line numberDiff line change
@@ -6048,6 +6048,174 @@ func TestStructOfTooLarge(t *testing.T) {
60486048
}
60496049
}
60506050

6051+
type EmbeddedStructZero struct{}
6052+
6053+
func (EmbeddedStructZero) MValue() int {
6054+
return 1234
6055+
}
6056+
6057+
func (*EmbeddedStructZero) MPtr() int {
6058+
return 5678
6059+
}
6060+
6061+
type EmbeddedStructSmall struct {
6062+
Field int
6063+
}
6064+
6065+
func (s EmbeddedStructSmall) MValue() int {
6066+
return s.Field + 1234
6067+
}
6068+
6069+
func (s *EmbeddedStructSmall) MPtr() int {
6070+
return s.Field + 5678
6071+
}
6072+
6073+
type EmbeddedStructLarge struct {
6074+
Field [33]int
6075+
}
6076+
6077+
func (s EmbeddedStructLarge) MValue() int {
6078+
return s.Field[17] + 1234
6079+
}
6080+
6081+
func (s *EmbeddedStructLarge) MPtr() int {
6082+
return s.Field[18] + 5678
6083+
}
6084+
6085+
type EmbeddedInterfaceValue interface {
6086+
MValue() int
6087+
}
6088+
6089+
type EmbeddedInterfacePtr interface {
6090+
MValue() int
6091+
MPtr() int
6092+
}
6093+
6094+
// Test methods from embedded fields. See #38783.
6095+
func TestStructOfMethods(t *testing.T) {
6096+
sZeroValue := New(StructOf([]StructField{
6097+
{
6098+
Name: "EmbeddedStructZero",
6099+
Type: TypeOf(EmbeddedStructZero{}),
6100+
Anonymous: true,
6101+
},
6102+
})).Elem()
6103+
rets := sZeroValue.MethodByName("MValue").Call([]Value{})
6104+
if rets[0].Int() != 1234 {
6105+
t.Errorf("embedded zero struct value call: have %d, want 1234",
6106+
rets[0].Int())
6107+
}
6108+
sSmallValue := New(StructOf([]StructField{
6109+
{
6110+
Name: "EmbeddedStructSmall",
6111+
Type: TypeOf(EmbeddedStructSmall{}),
6112+
Anonymous: true,
6113+
},
6114+
})).Elem()
6115+
sSmallValue.Field(0).Field(0).SetInt(42)
6116+
rets = sSmallValue.MethodByName("MValue").Call([]Value{})
6117+
if rets[0].Int() != 1234+42 {
6118+
t.Errorf("embedded small struct value call: have %d, want %d",
6119+
rets[0].Int(), 1234+42)
6120+
}
6121+
sLargeValue := New(StructOf([]StructField{
6122+
{
6123+
Name: "EmbeddedStructLarge",
6124+
Type: TypeOf(EmbeddedStructLarge{}),
6125+
Anonymous: true,
6126+
},
6127+
})).Elem()
6128+
sLargeValue.Field(0).Field(0).Index(17).SetInt(42)
6129+
sLargeValue.Field(0).Field(0).Index(18).SetInt(35)
6130+
rets = sLargeValue.MethodByName("MValue").Call([]Value{})
6131+
if rets[0].Int() != 1234+42 {
6132+
t.Errorf("embedded large struct value call: have %d, want %d",
6133+
rets[0].Int(), 1234+42)
6134+
}
6135+
var ifaceValue EmbeddedInterfaceValue
6136+
sIfaceValue := New(StructOf([]StructField{
6137+
{
6138+
Name: "EmbeddedInterfaceValue",
6139+
Type: TypeOf(&ifaceValue).Elem(),
6140+
Anonymous: true,
6141+
},
6142+
})).Elem()
6143+
sIfaceValue.Field(0).Set(ValueOf(EmbeddedStructZero{}))
6144+
rets = sIfaceValue.MethodByName("MValue").Call([]Value{})
6145+
if rets[0].Int() != 1234 {
6146+
t.Errorf("embedded zero struct interface value call: have %d, want 1234",
6147+
rets[0].Int())
6148+
}
6149+
sIfaceValue.Field(0).Set(ValueOf(EmbeddedStructSmall{42}))
6150+
rets = sIfaceValue.MethodByName("MValue").Call([]Value{})
6151+
if rets[0].Int() != 1234+42 {
6152+
t.Errorf("embedded small struct interface value call: have %d, want %d",
6153+
rets[0].Int(), 1234+42)
6154+
}
6155+
large := EmbeddedStructLarge{}
6156+
large.Field[17] = 42
6157+
large.Field[18] = 35
6158+
sIfaceValue.Field(0).Set(ValueOf(large))
6159+
rets = sIfaceValue.MethodByName("MValue").Call([]Value{})
6160+
if rets[0].Int() != 1234+42 {
6161+
t.Errorf("embedded large struct interface value call: have %d, want %d",
6162+
rets[0].Int(), 1234+42)
6163+
}
6164+
var ifacePtr EmbeddedInterfacePtr
6165+
sIfacePtr := New(StructOf([]StructField{
6166+
{
6167+
Name: "EmbeddedInterfacePtr",
6168+
Type: TypeOf(&ifacePtr).Elem(),
6169+
Anonymous: true,
6170+
},
6171+
})).Elem()
6172+
sIfacePtr.Field(0).Set(ValueOf(&EmbeddedStructZero{}))
6173+
rets = sIfacePtr.MethodByName("MValue").Call([]Value{})
6174+
if rets[0].Int() != 1234 {
6175+
t.Errorf(
6176+
"embedded zero struct ptr interface value call: have %d, want 1234",
6177+
rets[0].Int(),
6178+
)
6179+
}
6180+
rets = sIfacePtr.MethodByName("MPtr").Call([]Value{})
6181+
if rets[0].Int() != 5678 {
6182+
t.Errorf(
6183+
"embedded zero struct ptr interface ptr call: have %d, want 5678",
6184+
rets[0].Int(),
6185+
)
6186+
}
6187+
sIfacePtr.Field(0).Set(ValueOf(&EmbeddedStructSmall{42}))
6188+
rets = sIfacePtr.MethodByName("MValue").Call([]Value{})
6189+
if rets[0].Int() != 1234+42 {
6190+
t.Errorf(
6191+
"embedded small struct ptr interface value call: have %d, want %d",
6192+
rets[0].Int(), 1234+42,
6193+
)
6194+
}
6195+
rets = sIfacePtr.MethodByName("MPtr").Call([]Value{})
6196+
if rets[0].Int() != 5678+42 {
6197+
t.Errorf(
6198+
"embedded small struct ptr interface ptr call: have %d, want %d",
6199+
rets[0].Int(), 5678+42,
6200+
)
6201+
}
6202+
sIfacePtr.Field(0).Set(ValueOf(&large))
6203+
rets = sIfacePtr.MethodByName("MValue").Call([]Value{})
6204+
if rets[0].Int() != 1234+42 {
6205+
t.Errorf(
6206+
"embedded large struct ptr interface value call: have %d, want %d",
6207+
rets[0].Int(), 1234+42,
6208+
)
6209+
}
6210+
rets = sIfacePtr.MethodByName("MPtr").Call([]Value{})
6211+
if rets[0].Int() != 5678+35 {
6212+
t.Errorf(
6213+
"embedded large struct ptr interface ptr call: have %d, want %d",
6214+
rets[0].Int(), 5678+35,
6215+
)
6216+
}
6217+
}
6218+
60516219
func TestChanOf(t *testing.T) {
60526220
// check construction and use of type not in binary
60536221
type T string

0 commit comments

Comments
 (0)