diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index 4fd02e67ba..5ced5d3573 100644 --- a/src/internal/reflectlite/type.go +++ b/src/internal/reflectlite/type.go @@ -754,6 +754,98 @@ func (t *RawType) FieldAlign() int { return t.Align() } +// ConvertibleTo returns whether a value of type t can be converted to a variable of type u +func (r *RawType) ConvertibleTo(u *RawType) bool { + + // This logic is mostly copied from Value.CanConvert + + switch r.Kind() { + case Int, Int8, Int16, Int32, Int64: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + case String: + return true + } + + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + case String: + return true + } + + case Float32, Float64: + switch u.Kind() { + case Int, Int8, Int16, Int32, Int64: + return true + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + case Float32, Float64: + return true + } + + case Complex64, Complex128: + switch u.Kind() { + case Complex64, Complex128: + return true + } + + case Slice: + switch u.Kind() { + case Array: + // This may fail at runtime if there isn't room + if r.elem() == u.elem() { + return true + } + + case Pointer: + // This may fail at runtime if there isn't room + if u.elem().Kind() == Array && r.elem() == u.elem().elem() { + return true + } + + case String: + // bytes or runes + if !r.elem().isNamed() && (r.elem().Kind() == Uint8 || r.elem().Kind() == Int32) { + return true + } + + } + + case String: + // bytes or runes + if u.Kind() == Slice && !u.elem().isNamed() && (u.elem().Kind() == Uint8 || u.elem().Kind() == Int32) { + return true + } + + case Pointer: + if !r.isNamed() && u.Kind() == Pointer && !u.isNamed() && r.elem().underlying() == u.elem().underlying() { + return true + } + } + + if r.underlying() == u.underlying() { + return true + } + + if u.Kind() == Interface && u.NumMethod() == 0 { + return true + } + + // TODO(dgryski): Unimplemented + // struct types + // channels + + return false + +} + // AssignableTo returns whether a value of type t can be assigned to a variable // of type u. func (t *RawType) AssignableTo(u Type) bool { diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 5650c1266b..36cdac11e9 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -47,12 +47,21 @@ func (v Value) isExported() bool { return v.flags&valueFlagExported != 0 } -func (v Value) isRO() bool { +func (v Value) IsRO() bool { return v.flags&(valueFlagRO) != 0 } +func (v Value) MakeRO(ro bool) Value { + if ro { + v.flags |= valueFlagRO + } else { + v.flags &^= valueFlagRO + } + return v +} + func (v Value) checkRO() { - if v.isRO() { + if v.IsRO() { panic("reflect: value is not settable") } } @@ -297,7 +306,7 @@ func (v Value) IsValid() bool { } func (v Value) CanInterface() bool { - return v.isExported() && !v.isRO() + return v.isExported() && !v.IsRO() } func (v Value) CanAddr() bool { @@ -1485,13 +1494,11 @@ func convertOp(src Value, typ Type) (Value, bool) { return cvtFloat(src, rtype), true } - /* - case Complex64, Complex128: - switch src.Kind() { - case Complex64, Complex128: - return cvtComplex - } - */ + case Complex64, Complex128: + switch rtype := typ.(*RawType); rtype.Kind() { + case Complex64, Complex128: + return cvtComplex(src, rtype), true + } case Slice: switch rtype := typ.(*RawType); rtype.Kind() { @@ -1534,6 +1541,12 @@ func convertOp(src Value, typ Type) (Value, bool) { return cvtStringRunes(src, rtype), true } } + + case Pointer: + rtype := typ.(*RawType) + if rtype.Kind() == Pointer && !src.typecode.isNamed() && !rtype.isNamed() && src.typecode.elem().underlying() == rtype.elem().underlying() { + return cvtDirect(src, rtype), true + } } // TODO(dgryski): Unimplemented: @@ -1578,6 +1591,18 @@ func cvtFloat(v Value, t *RawType) Value { return makeFloat(v.flags, v.Float(), t) } +func cvtDirect(v Value, t *RawType) Value { + return Value{ + typecode: t, + value: v.value, + flags: v.flags, + } +} + +func cvtComplex(v Value, t *RawType) Value { + return makeComplex(v.flags, v.Complex(), t) +} + //go:linkname stringToBytes runtime.stringToBytes func stringToBytes(x string) []byte @@ -1661,20 +1686,76 @@ func makeFloat32(flags valueFlags, f float32, t *RawType) Value { return v } -func cvtIntString(src Value, t *RawType) Value { - panic("cvtUintString: unimplemented") +func makeComplex(flags valueFlags, f complex128, t *RawType) Value { + size := t.Size() + + v := Value{ + typecode: t, + flags: flags, + } + + ptr := unsafe.Pointer(&v.value) + if size > unsafe.Sizeof(uintptr(0)) { + ptr = alloc(size, nil) + v.value = ptr + } + + switch size { + case 8: + *(*complex64)(ptr) = complex64(f) + case 16: + *(*complex128)(ptr) = f + } + return v +} + +func cvtIntString(v Value, t *RawType) Value { + s := "\uFFFD" + if x := v.Int(); int64(rune(x)) == x { + s = string(rune(x)) + } + return Value{ + typecode: t, + value: unsafe.Pointer(&s), + flags: v.flags, + } } -func cvtUintString(src Value, t *RawType) Value { - panic("cvtUintString: unimplemented") +func cvtUintString(v Value, t *RawType) Value { + s := "\uFFFD" + if x := v.Uint(); uint64(rune(x)) == x { + s = string(rune(x)) + } + + return Value{ + typecode: t, + value: unsafe.Pointer(&s), + flags: v.flags, + } } -func cvtStringRunes(src Value, t *RawType) Value { - panic("cvsStringRunes: unimplemented") +//go:linkname stringToRunes runtime.stringToRunes +func stringToRunes(s string) []rune + +func cvtStringRunes(v Value, t *RawType) Value { + b := stringToRunes(*(*string)(v.value)) + return Value{ + typecode: t, + value: unsafe.Pointer(&b), + flags: v.flags, + } } -func cvtRunesString(src Value, t *RawType) Value { - panic("cvsRunesString: unimplemented") +//go:linkname stringFromRunes runtime.stringFromRunes +func stringFromRunes(r []rune) string + +func cvtRunesString(v Value, t *RawType) Value { + s := stringFromRunes(*(*[]rune)(v.value)) + return Value{ + typecode: t, + value: unsafe.Pointer(&s), + flags: v.flags, + } } //go:linkname slicePanic runtime.slicePanic diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index a755278623..7584c62055 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -4249,8 +4249,6 @@ type BytesChan chan []byte type BytesChanRecv <-chan []byte type BytesChanSend chan<- []byte -/* - var convertTests = []struct { in Value out Value @@ -4286,7 +4284,7 @@ var convertTests = []struct { } } } -*/ /* + */ {V(int8(1)), V(int8(1))}, {V(int8(2)), V(uint8(2))}, {V(uint8(3)), V(int8(3))}, @@ -4602,37 +4600,41 @@ var convertTests = []struct { {V((func())(nil)), V(MyFunc(nil))}, {V((MyFunc)(nil)), V((func())(nil))}, - // structs with different tags - {V(struct { - x int `some:"foo"` - }{}), V(struct { - x int `some:"bar"` - }{})}, + /* + + // structs with different tags + {V(struct { + x int `some:"foo"` + }{}), V(struct { + x int `some:"bar"` + }{})}, - {V(struct { - x int `some:"bar"` - }{}), V(struct { - x int `some:"foo"` - }{})}, + {V(struct { + x int `some:"bar"` + }{}), V(struct { + x int `some:"foo"` + }{})}, - {V(MyStruct{}), V(struct { - x int `some:"foo"` - }{})}, + {V(MyStruct{}), V(struct { + x int `some:"foo"` + }{})}, - {V(struct { - x int `some:"foo"` - }{}), V(MyStruct{})}, + {V(struct { + x int `some:"foo"` + }{}), V(MyStruct{})}, - {V(MyStruct{}), V(struct { - x int `some:"bar"` - }{})}, + {V(MyStruct{}), V(struct { + x int `some:"bar"` + }{})}, - {V(struct { - x int `some:"bar"` - }{}), V(MyStruct{})}, + {V(struct { + x int `some:"bar"` + }{}), V(MyStruct{})}, - {V(MyStruct1{}), V(MyStruct2{})}, - {V(MyStruct2{}), V(MyStruct1{})}, + + {V(MyStruct1{}), V(MyStruct2{})}, + {V(MyStruct2{}), V(MyStruct1{})}, + */ // can convert *byte and *MyByte {V((*byte)(nil)), V((*MyByte)(nil))}, @@ -4674,46 +4676,58 @@ var convertTests = []struct { {V(new(io.Reader)), V(new(io.Reader))}, {V(new(io.Writer)), V(new(io.Writer))}, - // channels - {V(IntChan(nil)), V((chan<- int)(nil))}, - {V(IntChan(nil)), V((<-chan int)(nil))}, - {V((chan int)(nil)), V(IntChanRecv(nil))}, - {V((chan int)(nil)), V(IntChanSend(nil))}, - {V(IntChanRecv(nil)), V((<-chan int)(nil))}, - {V((<-chan int)(nil)), V(IntChanRecv(nil))}, - {V(IntChanSend(nil)), V((chan<- int)(nil))}, - {V((chan<- int)(nil)), V(IntChanSend(nil))}, - {V(IntChan(nil)), V((chan int)(nil))}, - {V((chan int)(nil)), V(IntChan(nil))}, - {V((chan int)(nil)), V((<-chan int)(nil))}, - {V((chan int)(nil)), V((chan<- int)(nil))}, - {V(BytesChan(nil)), V((chan<- []byte)(nil))}, - {V(BytesChan(nil)), V((<-chan []byte)(nil))}, - {V((chan []byte)(nil)), V(BytesChanRecv(nil))}, - {V((chan []byte)(nil)), V(BytesChanSend(nil))}, - {V(BytesChanRecv(nil)), V((<-chan []byte)(nil))}, - {V((<-chan []byte)(nil)), V(BytesChanRecv(nil))}, - {V(BytesChanSend(nil)), V((chan<- []byte)(nil))}, - {V((chan<- []byte)(nil)), V(BytesChanSend(nil))}, - {V(BytesChan(nil)), V((chan []byte)(nil))}, - {V((chan []byte)(nil)), V(BytesChan(nil))}, - {V((chan []byte)(nil)), V((<-chan []byte)(nil))}, - {V((chan []byte)(nil)), V((chan<- []byte)(nil))}, - - // cannot convert other instances (channels) - {V(IntChan(nil)), V(IntChan(nil))}, - {V(IntChanRecv(nil)), V(IntChanRecv(nil))}, - {V(IntChanSend(nil)), V(IntChanSend(nil))}, - {V(BytesChan(nil)), V(BytesChan(nil))}, - {V(BytesChanRecv(nil)), V(BytesChanRecv(nil))}, - {V(BytesChanSend(nil)), V(BytesChanSend(nil))}, - - // interfaces - {V(int(1)), EmptyInterfaceV(int(1))}, - {V(string("hello")), EmptyInterfaceV(string("hello"))}, - {V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, - {ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, - {V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))}, + /* + + // channels + {V(IntChan(nil)), V((chan<- int)(nil))}, + {V(IntChan(nil)), V((<-chan int)(nil))}, + {V((chan int)(nil)), V(IntChanRecv(nil))}, + {V((chan int)(nil)), V(IntChanSend(nil))}, + {V(IntChanRecv(nil)), V((<-chan int)(nil))}, + {V((<-chan int)(nil)), V(IntChanRecv(nil))}, + {V(IntChanSend(nil)), V((chan<- int)(nil))}, + {V((chan<- int)(nil)), V(IntChanSend(nil))}, + {V(IntChan(nil)), V((chan int)(nil))}, + {V((chan int)(nil)), V(IntChan(nil))}, + {V((chan int)(nil)), V((<-chan int)(nil))}, + {V((chan int)(nil)), V((chan<- int)(nil))}, + {V(BytesChan(nil)), V((chan<- []byte)(nil))}, + {V(BytesChan(nil)), V((<-chan []byte)(nil))}, + {V((chan []byte)(nil)), V(BytesChanRecv(nil))}, + {V((chan []byte)(nil)), V(BytesChanSend(nil))}, + {V(BytesChanRecv(nil)), V((<-chan []byte)(nil))}, + {V((<-chan []byte)(nil)), V(BytesChanRecv(nil))}, + {V(BytesChanSend(nil)), V((chan<- []byte)(nil))}, + {V((chan<- []byte)(nil)), V(BytesChanSend(nil))}, + {V(BytesChan(nil)), V((chan []byte)(nil))}, + {V((chan []byte)(nil)), V(BytesChan(nil))}, + {V((chan []byte)(nil)), V((<-chan []byte)(nil))}, + {V((chan []byte)(nil)), V((chan<- []byte)(nil))}, + + // cannot convert other instances (channels) + {V(IntChan(nil)), V(IntChan(nil))}, + {V(IntChanRecv(nil)), V(IntChanRecv(nil))}, + {V(IntChanSend(nil)), V(IntChanSend(nil))}, + {V(BytesChan(nil)), V(BytesChan(nil))}, + {V(BytesChanRecv(nil)), V(BytesChanRecv(nil))}, + {V(BytesChanSend(nil)), V(BytesChanSend(nil))}, + + // interfaces + {V(int(1)), EmptyInterfaceV(int(1))}, + {V(string("hello")), EmptyInterfaceV(string("hello"))}, + {V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, + {ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))}, + {V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))}, + */ + +} + +func IsRO(v Value) bool { + return v.IsRO() +} + +func MakeRO(v Value) Value { + return Value{v.MakeRO(true)} } func TestConvert(t *testing.T) { @@ -4804,6 +4818,8 @@ func TestConvert(t *testing.T) { } } +/* + func TestConvertPanic(t *testing.T) { s := make([]byte, 4) p := new([8]byte) @@ -4848,6 +4864,8 @@ func TestConvertSlice2Array(t *testing.T) { } } +*/ + var gFloat32 float32 const snan uint32 = 0x7f800001 @@ -4870,8 +4888,6 @@ func TestConvertNaNs(t *testing.T) { } } -*/ - type ComparableStruct struct { X int } diff --git a/src/reflect/convert_test.go b/src/reflect/convert_test.go deleted file mode 100644 index 601bae5883..0000000000 --- a/src/reflect/convert_test.go +++ /dev/null @@ -1,192 +0,0 @@ -package reflect_test - -import ( - . "reflect" - "testing" -) - -func TestTinyConvert(t *testing.T) { - - V := ValueOf - - var tests = []struct { - have, want Value - }{ - {V(int8(1)), V(int8(1))}, - {V(int8(2)), V(uint8(2))}, - {V(uint8(3)), V(int8(3))}, - {V(int8(4)), V(int16(4))}, - {V(int16(5)), V(int8(5))}, - {V(int8(6)), V(uint16(6))}, - {V(uint16(7)), V(int8(7))}, - {V(int8(8)), V(int32(8))}, - {V(int32(9)), V(int8(9))}, - {V(int8(10)), V(uint32(10))}, - {V(uint32(11)), V(int8(11))}, - {V(int8(12)), V(int64(12))}, - {V(int64(13)), V(int8(13))}, - {V(int8(14)), V(uint64(14))}, - {V(uint64(15)), V(int8(15))}, - {V(int8(16)), V(int(16))}, - {V(int(17)), V(int8(17))}, - {V(int8(18)), V(uint(18))}, - {V(uint(19)), V(int8(19))}, - {V(int8(20)), V(uintptr(20))}, - {V(uintptr(21)), V(int8(21))}, - {V(int8(22)), V(float32(22))}, - {V(float32(23)), V(int8(23))}, - {V(int8(24)), V(float64(24))}, - {V(float64(25)), V(int8(25))}, - {V(uint8(26)), V(uint8(26))}, - {V(uint8(27)), V(int16(27))}, - {V(int16(28)), V(uint8(28))}, - {V(uint8(29)), V(uint16(29))}, - {V(uint16(30)), V(uint8(30))}, - {V(uint8(31)), V(int32(31))}, - {V(int32(32)), V(uint8(32))}, - {V(uint8(33)), V(uint32(33))}, - {V(uint32(34)), V(uint8(34))}, - {V(uint8(35)), V(int64(35))}, - {V(int64(36)), V(uint8(36))}, - {V(uint8(37)), V(uint64(37))}, - {V(uint64(38)), V(uint8(38))}, - {V(uint8(39)), V(int(39))}, - {V(int(40)), V(uint8(40))}, - {V(uint8(41)), V(uint(41))}, - {V(uint(42)), V(uint8(42))}, - {V(uint8(43)), V(uintptr(43))}, - {V(uintptr(44)), V(uint8(44))}, - {V(uint8(45)), V(float32(45))}, - {V(float32(46)), V(uint8(46))}, - {V(uint8(47)), V(float64(47))}, - {V(float64(48)), V(uint8(48))}, - {V(int16(49)), V(int16(49))}, - {V(int16(50)), V(uint16(50))}, - {V(uint16(51)), V(int16(51))}, - {V(int16(52)), V(int32(52))}, - {V(int32(53)), V(int16(53))}, - {V(int16(54)), V(uint32(54))}, - {V(uint32(55)), V(int16(55))}, - {V(int16(56)), V(int64(56))}, - {V(int64(57)), V(int16(57))}, - {V(int16(58)), V(uint64(58))}, - {V(uint64(59)), V(int16(59))}, - {V(int16(60)), V(int(60))}, - {V(int(61)), V(int16(61))}, - {V(int16(62)), V(uint(62))}, - {V(uint(63)), V(int16(63))}, - {V(int16(64)), V(uintptr(64))}, - {V(uintptr(65)), V(int16(65))}, - {V(int16(66)), V(float32(66))}, - {V(float32(67)), V(int16(67))}, - {V(int16(68)), V(float64(68))}, - {V(float64(69)), V(int16(69))}, - {V(uint16(70)), V(uint16(70))}, - {V(uint16(71)), V(int32(71))}, - {V(int32(72)), V(uint16(72))}, - {V(uint16(73)), V(uint32(73))}, - {V(uint32(74)), V(uint16(74))}, - {V(uint16(75)), V(int64(75))}, - {V(int64(76)), V(uint16(76))}, - {V(uint16(77)), V(uint64(77))}, - {V(uint64(78)), V(uint16(78))}, - {V(uint16(79)), V(int(79))}, - {V(int(80)), V(uint16(80))}, - {V(uint16(81)), V(uint(81))}, - {V(uint(82)), V(uint16(82))}, - {V(uint16(83)), V(uintptr(83))}, - {V(uintptr(84)), V(uint16(84))}, - {V(uint16(85)), V(float32(85))}, - {V(float32(86)), V(uint16(86))}, - {V(uint16(87)), V(float64(87))}, - {V(float64(88)), V(uint16(88))}, - {V(int32(89)), V(int32(89))}, - {V(int32(90)), V(uint32(90))}, - {V(uint32(91)), V(int32(91))}, - {V(int32(92)), V(int64(92))}, - {V(int64(93)), V(int32(93))}, - {V(int32(94)), V(uint64(94))}, - {V(uint64(95)), V(int32(95))}, - {V(int32(96)), V(int(96))}, - {V(int(97)), V(int32(97))}, - {V(int32(98)), V(uint(98))}, - {V(uint(99)), V(int32(99))}, - {V(int32(100)), V(uintptr(100))}, - {V(uintptr(101)), V(int32(101))}, - {V(int32(102)), V(float32(102))}, - {V(float32(103)), V(int32(103))}, - {V(int32(104)), V(float64(104))}, - {V(float64(105)), V(int32(105))}, - {V(uint32(106)), V(uint32(106))}, - {V(uint32(107)), V(int64(107))}, - {V(int64(108)), V(uint32(108))}, - {V(uint32(109)), V(uint64(109))}, - {V(uint64(110)), V(uint32(110))}, - {V(uint32(111)), V(int(111))}, - {V(int(112)), V(uint32(112))}, - {V(uint32(113)), V(uint(113))}, - {V(uint(114)), V(uint32(114))}, - {V(uint32(115)), V(uintptr(115))}, - {V(uintptr(116)), V(uint32(116))}, - {V(uint32(117)), V(float32(117))}, - {V(float32(118)), V(uint32(118))}, - {V(uint32(119)), V(float64(119))}, - {V(float64(120)), V(uint32(120))}, - {V(int64(121)), V(int64(121))}, - {V(int64(122)), V(uint64(122))}, - {V(uint64(123)), V(int64(123))}, - {V(int64(124)), V(int(124))}, - {V(int(125)), V(int64(125))}, - {V(int64(126)), V(uint(126))}, - {V(uint(127)), V(int64(127))}, - {V(int64(128)), V(uintptr(128))}, - {V(uintptr(129)), V(int64(129))}, - {V(int64(130)), V(float32(130))}, - {V(float32(131)), V(int64(131))}, - {V(int64(132)), V(float64(132))}, - {V(float64(133)), V(int64(133))}, - {V(uint64(134)), V(uint64(134))}, - {V(uint64(135)), V(int(135))}, - {V(int(136)), V(uint64(136))}, - {V(uint64(137)), V(uint(137))}, - {V(uint(138)), V(uint64(138))}, - {V(uint64(139)), V(uintptr(139))}, - {V(uintptr(140)), V(uint64(140))}, - {V(uint64(141)), V(float32(141))}, - {V(float32(142)), V(uint64(142))}, - {V(uint64(143)), V(float64(143))}, - {V(float64(144)), V(uint64(144))}, - {V(int(145)), V(int(145))}, - {V(int(146)), V(uint(146))}, - {V(uint(147)), V(int(147))}, - {V(int(148)), V(uintptr(148))}, - {V(uintptr(149)), V(int(149))}, - {V(int(150)), V(float32(150))}, - {V(float32(151)), V(int(151))}, - {V(int(152)), V(float64(152))}, - {V(float64(153)), V(int(153))}, - {V(uint(154)), V(uint(154))}, - {V(uint(155)), V(uintptr(155))}, - {V(uintptr(156)), V(uint(156))}, - {V(uint(157)), V(float32(157))}, - {V(float32(158)), V(uint(158))}, - {V(uint(159)), V(float64(159))}, - {V(float64(160)), V(uint(160))}, - {V(uintptr(161)), V(uintptr(161))}, - {V(uintptr(162)), V(float32(162))}, - {V(float32(163)), V(uintptr(163))}, - {V(uintptr(164)), V(float64(164))}, - {V(float64(165)), V(uintptr(165))}, - {V(float32(166)), V(float32(166))}, - {V(float32(167)), V(float64(167))}, - {V(float64(168)), V(float32(168))}, - {V(float64(169)), V(float64(169))}, - } - - for _, tt := range tests { - got := tt.have.Convert(tt.want.Type()) - if !DeepEqual(got.Interface(), tt.want.Interface()) { - t.Errorf("Failed to Convert() %T(%v) -> %T(%v), got %T(%v)", tt.have.Interface(), tt.have, tt.want.Interface(), tt.want, got.Interface(), got) - } - } -} diff --git a/src/reflect/type.go b/src/reflect/type.go index 884f89dc84..777db1a81e 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -402,7 +402,7 @@ func (t *rawType) CanSeq2() bool { } func (t *rawType) ConvertibleTo(u Type) bool { - panic("unimplemented: (reflect.Type).ConvertibleTo()") + return t.RawType.ConvertibleTo(&(u.(*rawType).RawType)) } func (t *rawType) Elem() Type { diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index 999c115cb7..9efc36f774 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -628,7 +628,7 @@ func TestAssignableTo(t *testing.T) { } } -func TestConvert(t *testing.T) { +func TestConvertBasic(t *testing.T) { v := ValueOf(int64(3)) c := v.Convert(TypeOf(byte(0))) diff --git a/src/runtime/string.go b/src/runtime/string.go index d4ee5e3c1a..cdc31cb16c 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -153,7 +153,9 @@ func stringNext(s string, it *stringIterator) (bool, int, rune) { } // Convert a Unicode code point into an array of bytes and its length. -func encodeUTF8(x rune) ([4]byte, uintptr) { +func encodeUTF8(r rune) ([4]byte, uintptr) { + x := uint32(r) + // https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16 // Note: this code can probably be optimized (in size and speed). switch {