mirror of
https://github.com/golang/go
synced 2024-09-29 14:14:29 -06:00
reflect: record PkgPath of StructOf arguments
Fixes #36190 Fixes #36191 Change-Id: I1213ef37b6595af63dbe202a8ade65741caf1356 Reviewed-on: https://go-review.googlesource.com/c/go/+/212001 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
dcdee153cd
commit
ba66797392
@ -4853,6 +4853,9 @@ func TestStructOfExportRules(t *testing.T) {
|
|||||||
if exported != test.exported {
|
if exported != test.exported {
|
||||||
t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported)
|
t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported)
|
||||||
}
|
}
|
||||||
|
if field.PkgPath != test.field.PkgPath {
|
||||||
|
t.Errorf("test-%d: got PkgPath=%q want pkgPath=%q", i, field.PkgPath, test.field.PkgPath)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5308,6 +5311,24 @@ func TestStructOfTooManyFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStructOfDifferentPkgPath(t *testing.T) {
|
||||||
|
fields := []StructField{
|
||||||
|
{
|
||||||
|
Name: "f1",
|
||||||
|
PkgPath: "p1",
|
||||||
|
Type: TypeOf(int(0)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "f2",
|
||||||
|
PkgPath: "p2",
|
||||||
|
Type: TypeOf(int(0)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
shouldPanic(func() {
|
||||||
|
StructOf(fields)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestChanOf(t *testing.T) {
|
func TestChanOf(t *testing.T) {
|
||||||
// check construction and use of type not in binary
|
// check construction and use of type not in binary
|
||||||
type T string
|
type T string
|
||||||
|
@ -2371,6 +2371,7 @@ func StructOf(fields []StructField) Type {
|
|||||||
|
|
||||||
lastzero := uintptr(0)
|
lastzero := uintptr(0)
|
||||||
repr = append(repr, "struct {"...)
|
repr = append(repr, "struct {"...)
|
||||||
|
pkgpath := ""
|
||||||
for i, field := range fields {
|
for i, field := range fields {
|
||||||
if field.Name == "" {
|
if field.Name == "" {
|
||||||
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
|
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
|
||||||
@ -2381,11 +2382,18 @@ func StructOf(fields []StructField) Type {
|
|||||||
if field.Type == nil {
|
if field.Type == nil {
|
||||||
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
|
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
|
||||||
}
|
}
|
||||||
f := runtimeStructField(field)
|
f, fpkgpath := runtimeStructField(field)
|
||||||
ft := f.typ
|
ft := f.typ
|
||||||
if ft.kind&kindGCProg != 0 {
|
if ft.kind&kindGCProg != 0 {
|
||||||
hasGCProg = true
|
hasGCProg = true
|
||||||
}
|
}
|
||||||
|
if fpkgpath != "" {
|
||||||
|
if pkgpath == "" {
|
||||||
|
pkgpath = fpkgpath
|
||||||
|
} else if pkgpath != fpkgpath {
|
||||||
|
panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update string and hash
|
// Update string and hash
|
||||||
name := f.name.name()
|
name := f.name.name()
|
||||||
@ -2617,6 +2625,9 @@ func StructOf(fields []StructField) Type {
|
|||||||
prototype := *(**structType)(unsafe.Pointer(&istruct))
|
prototype := *(**structType)(unsafe.Pointer(&istruct))
|
||||||
*typ = *prototype
|
*typ = *prototype
|
||||||
typ.fields = fs
|
typ.fields = fs
|
||||||
|
if pkgpath != "" {
|
||||||
|
typ.pkgPath = newName(pkgpath, "", false)
|
||||||
|
}
|
||||||
|
|
||||||
// Look in cache.
|
// Look in cache.
|
||||||
if ts, ok := structLookupCache.m.Load(hash); ok {
|
if ts, ok := structLookupCache.m.Load(hash); ok {
|
||||||
@ -2741,7 +2752,10 @@ func StructOf(fields []StructField) Type {
|
|||||||
return addToCache(&typ.rtype)
|
return addToCache(&typ.rtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runtimeStructField(field StructField) structField {
|
// runtimeStructField takes a StructField value passed to StructOf and
|
||||||
|
// returns both the corresponding internal representation, of type
|
||||||
|
// structField, and the pkgpath value to use for this field.
|
||||||
|
func runtimeStructField(field StructField) (structField, string) {
|
||||||
if field.Anonymous && field.PkgPath != "" {
|
if field.Anonymous && field.PkgPath != "" {
|
||||||
panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
|
panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
|
||||||
}
|
}
|
||||||
@ -2762,11 +2776,12 @@ func runtimeStructField(field StructField) structField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolveReflectType(field.Type.common()) // install in runtime
|
resolveReflectType(field.Type.common()) // install in runtime
|
||||||
return structField{
|
f := structField{
|
||||||
name: newName(field.Name, string(field.Tag), exported),
|
name: newName(field.Name, string(field.Tag), exported),
|
||||||
typ: field.Type.common(),
|
typ: field.Type.common(),
|
||||||
offsetEmbed: offsetEmbed,
|
offsetEmbed: offsetEmbed,
|
||||||
}
|
}
|
||||||
|
return f, field.PkgPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeptrdata returns the length in bytes of the prefix of t
|
// typeptrdata returns the length in bytes of the prefix of t
|
||||||
|
Loading…
Reference in New Issue
Block a user