Commit 0e4a0b93 authored by Raghavendra Nagaraj's avatar Raghavendra Nagaraj Committed by Ian Lance Taylor

reflect: fix StructOf panics from too many methods in embedded fields

Previously we panicked if the number of methods present for an embedded
field was >= 32. This change removes that limit and now StructOf
dynamically calls itself to create space for the number of methods.

Fixes #25402

Change-Id: I3b1deb119796d25f7e6eee1cdb126327b49a0b5e
GitHub-Last-Rev: 16da71ad6b23563f3ed26f1914adf41e3d42de69
GitHub-Pull-Request: golang/go#26865
Reviewed-on: https://go-review.googlesource.com/c/128479
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 510eea2d
......@@ -5019,6 +5019,17 @@ func TestStructOfWithInterface(t *testing.T) {
})
}
func TestStructOfTooManyFields(t *testing.T) {
// Bug Fix: #25402 - this should not panic
tt := StructOf([]StructField{
{Name: "Time", Type: TypeOf(time.Time{}), Anonymous: true},
})
if _, present := tt.MethodByName("After"); !present {
t.Errorf("Expected method `After` to be found")
}
}
func TestChanOf(t *testing.T) {
// check construction and use of type not in binary
type T string
......
......@@ -1889,6 +1889,8 @@ func MapOf(key, elem Type) Type {
return ti.(Type)
}
// TODO(crawshaw): as these funcTypeFixedN structs have no methods,
// they could be defined at runtime using the StructOf function.
type funcTypeFixed4 struct {
funcType
args [4]*rtype
......@@ -2278,42 +2280,6 @@ type structTypeUncommon struct {
u uncommonType
}
// A *rtype representing a struct is followed directly in memory by an
// array of method objects representing the methods attached to the
// struct. To get the same layout for a run time generated type, we
// need an array directly following the uncommonType memory. The types
// structTypeFixed4, ...structTypeFixedN are used to do this.
//
// A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN.
// TODO(crawshaw): as these structTypeFixedN and funcTypeFixedN structs
// have no methods, they could be defined at runtime using the StructOf
// function.
type structTypeFixed4 struct {
structType
u uncommonType
m [4]method
}
type structTypeFixed8 struct {
structType
u uncommonType
m [8]method
}
type structTypeFixed16 struct {
structType
u uncommonType
m [16]method
}
type structTypeFixed32 struct {
structType
u uncommonType
m [32]method
}
// isLetter reports whether a given 'rune' is classified as a Letter.
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
......@@ -2571,33 +2537,26 @@ func StructOf(fields []StructField) Type {
var typ *structType
var ut *uncommonType
switch {
case len(methods) == 0:
if len(methods) == 0 {
t := new(structTypeUncommon)
typ = &t.structType
ut = &t.u
case len(methods) <= 4:
t := new(structTypeFixed4)
typ = &t.structType
ut = &t.u
copy(t.m[:], methods)
case len(methods) <= 8:
t := new(structTypeFixed8)
typ = &t.structType
ut = &t.u
copy(t.m[:], methods)
case len(methods) <= 16:
t := new(structTypeFixed16)
typ = &t.structType
ut = &t.u
copy(t.m[:], methods)
case len(methods) <= 32:
t := new(structTypeFixed32)
typ = &t.structType
ut = &t.u
copy(t.m[:], methods)
default:
panic("reflect.StructOf: too many methods")
} else {
// A *rtype representing a struct is followed directly in memory by an
// array of method objects representing the methods attached to the
// struct. To get the same layout for a run time generated type, we
// need an array directly following the uncommonType memory.
// A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN.
tt := New(StructOf([]StructField{
{Name: "S", Type: TypeOf(structType{})},
{Name: "U", Type: TypeOf(uncommonType{})},
{Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
}))
typ = (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
ut = (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr()))
copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]method), methods)
}
// TODO(sbinet): Once we allow embedding multiple types,
// methods will need to be sorted like the compiler does.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment