Skip to content

Commit ba66797

Browse files
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 <[email protected]>
1 parent dcdee15 commit ba66797

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

src/reflect/all_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4853,6 +4853,9 @@ func TestStructOfExportRules(t *testing.T) {
48534853
if exported != test.exported {
48544854
t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported)
48554855
}
4856+
if field.PkgPath != test.field.PkgPath {
4857+
t.Errorf("test-%d: got PkgPath=%q want pkgPath=%q", i, field.PkgPath, test.field.PkgPath)
4858+
}
48564859
})
48574860
}
48584861
}
@@ -5308,6 +5311,24 @@ func TestStructOfTooManyFields(t *testing.T) {
53085311
}
53095312
}
53105313

5314+
func TestStructOfDifferentPkgPath(t *testing.T) {
5315+
fields := []StructField{
5316+
{
5317+
Name: "f1",
5318+
PkgPath: "p1",
5319+
Type: TypeOf(int(0)),
5320+
},
5321+
{
5322+
Name: "f2",
5323+
PkgPath: "p2",
5324+
Type: TypeOf(int(0)),
5325+
},
5326+
}
5327+
shouldPanic(func() {
5328+
StructOf(fields)
5329+
})
5330+
}
5331+
53115332
func TestChanOf(t *testing.T) {
53125333
// check construction and use of type not in binary
53135334
type T string

src/reflect/type.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,6 +2371,7 @@ func StructOf(fields []StructField) Type {
23712371

23722372
lastzero := uintptr(0)
23732373
repr = append(repr, "struct {"...)
2374+
pkgpath := ""
23742375
for i, field := range fields {
23752376
if field.Name == "" {
23762377
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
@@ -2381,11 +2382,18 @@ func StructOf(fields []StructField) Type {
23812382
if field.Type == nil {
23822383
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
23832384
}
2384-
f := runtimeStructField(field)
2385+
f, fpkgpath := runtimeStructField(field)
23852386
ft := f.typ
23862387
if ft.kind&kindGCProg != 0 {
23872388
hasGCProg = true
23882389
}
2390+
if fpkgpath != "" {
2391+
if pkgpath == "" {
2392+
pkgpath = fpkgpath
2393+
} else if pkgpath != fpkgpath {
2394+
panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
2395+
}
2396+
}
23892397

23902398
// Update string and hash
23912399
name := f.name.name()
@@ -2617,6 +2625,9 @@ func StructOf(fields []StructField) Type {
26172625
prototype := *(**structType)(unsafe.Pointer(&istruct))
26182626
*typ = *prototype
26192627
typ.fields = fs
2628+
if pkgpath != "" {
2629+
typ.pkgPath = newName(pkgpath, "", false)
2630+
}
26202631

26212632
// Look in cache.
26222633
if ts, ok := structLookupCache.m.Load(hash); ok {
@@ -2741,7 +2752,10 @@ func StructOf(fields []StructField) Type {
27412752
return addToCache(&typ.rtype)
27422753
}
27432754

2744-
func runtimeStructField(field StructField) structField {
2755+
// runtimeStructField takes a StructField value passed to StructOf and
2756+
// returns both the corresponding internal representation, of type
2757+
// structField, and the pkgpath value to use for this field.
2758+
func runtimeStructField(field StructField) (structField, string) {
27452759
if field.Anonymous && field.PkgPath != "" {
27462760
panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
27472761
}
@@ -2762,11 +2776,12 @@ func runtimeStructField(field StructField) structField {
27622776
}
27632777

27642778
resolveReflectType(field.Type.common()) // install in runtime
2765-
return structField{
2779+
f := structField{
27662780
name: newName(field.Name, string(field.Tag), exported),
27672781
typ: field.Type.common(),
27682782
offsetEmbed: offsetEmbed,
27692783
}
2784+
return f, field.PkgPath
27702785
}
27712786

27722787
// typeptrdata returns the length in bytes of the prefix of t

0 commit comments

Comments
 (0)