]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: allow conversions between slices of named {byte,rune} and string
authorKeith Randall <khr@golang.org>
Tue, 27 Jan 2026 19:06:18 +0000 (11:06 -0800)
committerKeith Randall <khr@google.com>
Tue, 27 Jan 2026 23:08:23 +0000 (15:08 -0800)
So the reflect behavior matches that of the language.

These conversions are allowed:

[]myByte <-> string
[]myRune <-> string
[]myByte <-> myString
[]myRune <-> myString

And even if the left-hand-side is named, e.g.

myBytes([]myByte) <-> string

Fixes #53523

Change-Id: I6562e72bc233a45dc7b02f75f68020831ad399ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/739680
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/reflect/all_test.go
src/reflect/value.go

index 54a80e98c7eb5fb22a3751c7467aee883bb63908..c15b5882ede5548e1c1bf6171793e22a96bde859 100644 (file)
@@ -4177,6 +4177,9 @@ type MyBytesArray [4]byte
 type MyRunes []int32
 type MyFunc func()
 type MyByte byte
+type MyRune rune
+type MyBytes2 []MyByte
+type MyRunes2 []MyRune
 
 type IntChan chan int
 type IntChanRecv <-chan int
@@ -4480,6 +4483,38 @@ var convertTests = []struct {
        {V(MyString("runes♝")), V(MyRunes("runes♝"))},
        {V(MyRunes("runes♕")), V(MyString("runes♕"))},
 
+       // []namedByte
+       {V(string("namedByte1")), V([]MyByte("namedByte1"))},
+       {V(MyString("namedByte2")), V([]MyByte("namedByte2"))},
+       {V([]MyByte("namedByte3")), V(string("namedByte3"))},
+       {V([]MyByte("namedByte4")), V(MyString("namedByte4"))},
+
+       // []namedRune
+       {V(string("namedRune1")), V([]MyRune("namedRune1"))},
+       {V(MyString("namedRune2")), V([]MyRune("namedRune2"))},
+       {V([]MyRune("namedRune3")), V(string("namedRune3"))},
+       {V([]MyRune("namedRune4")), V(MyString("namedRune4"))},
+
+       // named []namedByte
+       {V(string("namedByte5")), V(MyBytes2("namedByte5"))},
+       {V(MyString("namedByte6")), V(MyBytes2("namedByte6"))},
+       {V(MyBytes2("namedByte7")), V(string("namedByte7"))},
+       {V(MyBytes2("namedByte8")), V(MyString("namedByte8"))},
+
+       // named []namedRune
+       {V(string("namedRune5")), V(MyRunes2("namedRune5"))},
+       {V(MyString("namedRune6")), V(MyRunes2("namedRune6"))},
+       {V(MyRunes2("namedRune7")), V(string("namedRune7"))},
+       {V(MyRunes2("namedRune8")), V(MyString("namedRune8"))},
+
+       // random ok conversions of the above types
+       {V(MyBytes2("")), V([0]MyByte{})},
+       {V(MyBytes2("AA")), V([2]MyByte{65, 65})},
+       {V(MyBytes2("")), V([]MyByte{})},
+       {V([]MyByte{}), V(MyBytes2(""))},
+       {V([]MyRune("namedRuneA")), V(MyRunes2("namedRuneA"))},
+       {V(MyRunes2("namedRuneB")), V([]MyRune("namedRuneB"))},
+
        // slice to array
        {V([]byte(nil)), V([0]byte{})},
        {V([]byte{}), V([0]byte{})},
index 8c8acbaa9abdeb1ded8db01ef7d8cbbd5a9bf4c5..6fba1e751f0da28d764eaa8d83ecf5b4d2785df9 100644 (file)
@@ -3404,7 +3404,7 @@ func convertOp(dst, src *abi.Type) func(Value, Type) Value {
                }
 
        case String:
-               if dst.Kind() == abi.Slice && pkgPathFor(dst.Elem()) == "" {
+               if dst.Kind() == abi.Slice {
                        switch Kind(dst.Elem().Kind()) {
                        case Uint8:
                                return cvtStringBytes
@@ -3414,7 +3414,7 @@ func convertOp(dst, src *abi.Type) func(Value, Type) Value {
                }
 
        case Slice:
-               if dst.Kind() == abi.String && pkgPathFor(src.Elem()) == "" {
+               if dst.Kind() == abi.String {
                        switch Kind(src.Elem().Kind()) {
                        case Uint8:
                                return cvtBytesString