]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: let StructOf define unexported fields
authorDavid Crawshaw <crawshaw@golang.org>
Tue, 2 Jan 2018 17:43:41 +0000 (09:43 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 28 Sep 2019 00:19:19 +0000 (00:19 +0000)
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: Ian Lance Taylor <iant@golang.org>
doc/go1.14.html
src/reflect/all_test.go
src/reflect/type.go

index 525a1421f7d8fe7df5b469928ad28e28a17ad032..e68cca56df1e3528c0d6812e7ef9ba6389185c19 100644 (file)
@@ -115,6 +115,19 @@ TODO
 
 </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>
   <dd>
     <p><!-- CL 187739 -->
index fbb6feb0d98f21b0bdff7437b117d08a4171ee2d..7c5dd59aa78ca9bddb731f78264fe33c91d587f4 100644 (file)
@@ -4733,17 +4733,14 @@ func TestStructOfExportRules(t *testing.T) {
                        mustPanic: true,
                },
                {
-                       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: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
                },
                {
-                       field:     StructField{Name: "S", Type: TypeOf(S1{})},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S", Type: TypeOf(S1{})},
+                       exported: true,
                },
                {
                        field:    StructField{Name: "S", Type: TypeOf((*S1)(nil))},
@@ -4774,20 +4771,16 @@ func TestStructOfExportRules(t *testing.T) {
                        mustPanic: true,
                },
                {
-                       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{}), 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((*S1)(nil)), 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{}), 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: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
                },
                {
                        field:     StructField{Name: "", Type: TypeOf(ΦType{})},
index 2cf912cf54e8beb5c680cc7ecc442a7ce19c2d58..f1f8ba93a440a5edf13c28e9e7be1dc5a0636e9a 100644 (file)
@@ -2731,15 +2731,18 @@ func StructOf(fields []StructField) Type {
 }
 
 func runtimeStructField(field StructField) structField {
-       if field.PkgPath != "" {
-               panic("reflect.StructOf: StructOf does not allow unexported fields")
+       if field.Anonymous && field.PkgPath != "" {
+               panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
        }
 
-       // Best-effort check for misuse.
-       // Since PkgPath is empty, not much harm done if Unicode lowercase slips through.
-       c := field.Name[0]
-       if 'a' <= c && c <= 'z' || c == '_' {
-               panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
+       exported := field.PkgPath == ""
+       if exported {
+               // Best-effort check for misuse.
+               // Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
+               c := field.Name[0]
+               if 'a' <= c && c <= 'z' || c == '_' {
+                       panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
+               }
        }
 
        offsetEmbed := uintptr(0)
@@ -2749,7 +2752,7 @@ func runtimeStructField(field StructField) structField {
 
        resolveReflectType(field.Type.common()) // install in runtime
        return structField{
-               name:        newName(field.Name, string(field.Tag), true),
+               name:        newName(field.Name, string(field.Tag), exported),
                typ:         field.Type.common(),
                offsetEmbed: offsetEmbed,
        }