Commit 2d1c0332 authored by David Crawshaw's avatar David Crawshaw Committed by Ian Lance Taylor

reflect: let StructOf define unexported fields

This was missing from the original StructOf CL because I couldn't
think of a use for it. Now I can: even with types used entirely
by reflect, unexported fields can be set using UnsafeAddr.

Change-Id: I5e7e3d81d16e8817cdd69d85796ce33930ef523b
Reviewed-on: https://go-review.googlesource.com/c/go/+/85661
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 739bf6b9
...@@ -115,6 +115,19 @@ TODO ...@@ -115,6 +115,19 @@ TODO
</dl><!-- plugin --> </dl><!-- plugin -->
<dl id="reflect">
<dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
<p><!-- CL 85661 -->
<a href="/pkg/reflect#StructOf"><code>StructOf</code></a> now
supports creating struct types with unexported fields, by
setting the <code>PkgPath</code> field in
a <code>StructField</code> element.
</p>
</dl><!-- reflect -->
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt> <dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
<dd> <dd>
<p><!-- CL 187739 --> <p><!-- CL 187739 -->
......
...@@ -4733,17 +4733,14 @@ func TestStructOfExportRules(t *testing.T) { ...@@ -4733,17 +4733,14 @@ func TestStructOfExportRules(t *testing.T) {
mustPanic: true, mustPanic: true,
}, },
{ {
field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"}, field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
mustPanic: true,
}, },
{ {
field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"}, field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
mustPanic: true,
}, },
{ {
field: StructField{Name: "S", Type: TypeOf(S1{})}, field: StructField{Name: "S", Type: TypeOf(S1{})},
mustPanic: false, exported: true,
exported: true,
}, },
{ {
field: StructField{Name: "S", Type: TypeOf((*S1)(nil))}, field: StructField{Name: "S", Type: TypeOf((*S1)(nil))},
...@@ -4774,20 +4771,16 @@ func TestStructOfExportRules(t *testing.T) { ...@@ -4774,20 +4771,16 @@ func TestStructOfExportRules(t *testing.T) {
mustPanic: true, mustPanic: true,
}, },
{ {
field: StructField{Name: "s", Type: TypeOf(S1{}), PkgPath: "other/pkg"}, field: StructField{Name: "s", Type: TypeOf(S1{}), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
}, },
{ {
field: StructField{Name: "s", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"}, field: StructField{Name: "s", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
}, },
{ {
field: StructField{Name: "s", Type: TypeOf(s2{}), PkgPath: "other/pkg"}, field: StructField{Name: "s", Type: TypeOf(s2{}), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
}, },
{ {
field: StructField{Name: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"}, field: StructField{Name: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
}, },
{ {
field: StructField{Name: "", Type: TypeOf(ΦType{})}, field: StructField{Name: "", Type: TypeOf(ΦType{})},
......
...@@ -2731,15 +2731,18 @@ func StructOf(fields []StructField) Type { ...@@ -2731,15 +2731,18 @@ func StructOf(fields []StructField) Type {
} }
func runtimeStructField(field StructField) structField { func runtimeStructField(field StructField) structField {
if field.PkgPath != "" { if field.Anonymous && field.PkgPath != "" {
panic("reflect.StructOf: StructOf does not allow unexported fields") panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
} }
// Best-effort check for misuse. exported := field.PkgPath == ""
// Since PkgPath is empty, not much harm done if Unicode lowercase slips through. if exported {
c := field.Name[0] // Best-effort check for misuse.
if 'a' <= c && c <= 'z' || c == '_' { // Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath") c := field.Name[0]
if 'a' <= c && c <= 'z' || c == '_' {
panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
}
} }
offsetEmbed := uintptr(0) offsetEmbed := uintptr(0)
...@@ -2749,7 +2752,7 @@ func runtimeStructField(field StructField) structField { ...@@ -2749,7 +2752,7 @@ func runtimeStructField(field StructField) structField {
resolveReflectType(field.Type.common()) // install in runtime resolveReflectType(field.Type.common()) // install in runtime
return structField{ return structField{
name: newName(field.Name, string(field.Tag), true), name: newName(field.Name, string(field.Tag), exported),
typ: field.Type.common(), typ: field.Type.common(),
offsetEmbed: offsetEmbed, offsetEmbed: offsetEmbed,
} }
......
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