mirror of
https://github.com/golang/go
synced 2024-11-23 02:10:03 -07:00
reflect: add Type.ConvertibleTo, Value.Convert (API CHANGE)
Fixes #4047. R=iant, r CC=golang-dev https://golang.org/cl/6500065
This commit is contained in:
parent
49aa74ef7f
commit
46f379cc2c
@ -7,6 +7,7 @@ package reflect_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@ -1068,6 +1069,8 @@ type caseInfo struct {
|
|||||||
panic bool
|
panic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var allselect = flag.Bool("allselect", false, "exhaustive select test")
|
||||||
|
|
||||||
func TestSelect(t *testing.T) {
|
func TestSelect(t *testing.T) {
|
||||||
selectWatch.once.Do(func() { go selectWatcher() })
|
selectWatch.once.Do(func() { go selectWatcher() })
|
||||||
|
|
||||||
@ -1091,6 +1094,9 @@ func TestSelect(t *testing.T) {
|
|||||||
if testing.Short() && n >= 1000 {
|
if testing.Short() && n >= 1000 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if n >= 100000 && !*allselect {
|
||||||
|
break
|
||||||
|
}
|
||||||
if n%100000 == 0 && testing.Verbose() {
|
if n%100000 == 0 && testing.Verbose() {
|
||||||
println("TestSelect", n)
|
println("TestSelect", n)
|
||||||
}
|
}
|
||||||
@ -2162,6 +2168,447 @@ func TestAlias(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var V = ValueOf
|
||||||
|
|
||||||
|
func EmptyInterfaceV(x interface{}) Value {
|
||||||
|
return ValueOf(&x).Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReaderV(x io.Reader) Value {
|
||||||
|
return ValueOf(&x).Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadWriterV(x io.ReadWriter) Value {
|
||||||
|
return ValueOf(&x).Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Empty struct{}
|
||||||
|
type MyString string
|
||||||
|
type MyBytes []byte
|
||||||
|
type MyRunes []int32
|
||||||
|
type MyFunc func()
|
||||||
|
type MyByte byte
|
||||||
|
|
||||||
|
var convertTests = []struct {
|
||||||
|
in Value
|
||||||
|
out Value
|
||||||
|
}{
|
||||||
|
// numbers
|
||||||
|
/*
|
||||||
|
Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var numbers = []string{
|
||||||
|
"int8", "uint8", "int16", "uint16",
|
||||||
|
"int32", "uint32", "int64", "uint64",
|
||||||
|
"int", "uint", "uintptr",
|
||||||
|
"float32", "float64",
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// all pairs but in an unusual order,
|
||||||
|
// to emit all the int8, uint8 cases
|
||||||
|
// before n grows too big.
|
||||||
|
n := 1
|
||||||
|
for i, f := range numbers {
|
||||||
|
for _, g := range numbers[i:] {
|
||||||
|
fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n)
|
||||||
|
n++
|
||||||
|
if f != g {
|
||||||
|
fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
{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))},
|
||||||
|
|
||||||
|
// truncation
|
||||||
|
{V(float64(1.5)), V(int(1))},
|
||||||
|
|
||||||
|
// complex
|
||||||
|
{V(complex64(1i)), V(complex64(1i))},
|
||||||
|
{V(complex64(2i)), V(complex128(2i))},
|
||||||
|
{V(complex128(3i)), V(complex64(3i))},
|
||||||
|
{V(complex128(4i)), V(complex128(4i))},
|
||||||
|
|
||||||
|
// string
|
||||||
|
{V(string("hello")), V(string("hello"))},
|
||||||
|
{V(string("bytes1")), V([]byte("bytes1"))},
|
||||||
|
{V([]byte("bytes2")), V(string("bytes2"))},
|
||||||
|
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
||||||
|
{V(string("runes♝")), V([]rune("runes♝"))},
|
||||||
|
{V([]rune("runes♕")), V(string("runes♕"))},
|
||||||
|
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||||
|
{V(int('a')), V(string("a"))},
|
||||||
|
{V(int8('a')), V(string("a"))},
|
||||||
|
{V(int16('a')), V(string("a"))},
|
||||||
|
{V(int32('a')), V(string("a"))},
|
||||||
|
{V(int64('a')), V(string("a"))},
|
||||||
|
{V(uint('a')), V(string("a"))},
|
||||||
|
{V(uint8('a')), V(string("a"))},
|
||||||
|
{V(uint16('a')), V(string("a"))},
|
||||||
|
{V(uint32('a')), V(string("a"))},
|
||||||
|
{V(uint64('a')), V(string("a"))},
|
||||||
|
{V(uintptr('a')), V(string("a"))},
|
||||||
|
{V(int(-1)), V(string("\uFFFD"))},
|
||||||
|
{V(int8(-2)), V(string("\uFFFD"))},
|
||||||
|
{V(int16(-3)), V(string("\uFFFD"))},
|
||||||
|
{V(int32(-4)), V(string("\uFFFD"))},
|
||||||
|
{V(int64(-5)), V(string("\uFFFD"))},
|
||||||
|
{V(uint(0x110001)), V(string("\uFFFD"))},
|
||||||
|
{V(uint32(0x110002)), V(string("\uFFFD"))},
|
||||||
|
{V(uint64(0x110003)), V(string("\uFFFD"))},
|
||||||
|
{V(uintptr(0x110004)), V(string("\uFFFD"))},
|
||||||
|
|
||||||
|
// named string
|
||||||
|
{V(MyString("hello")), V(string("hello"))},
|
||||||
|
{V(string("hello")), V(MyString("hello"))},
|
||||||
|
{V(string("hello")), V(string("hello"))},
|
||||||
|
{V(MyString("hello")), V(MyString("hello"))},
|
||||||
|
{V(MyString("bytes1")), V([]byte("bytes1"))},
|
||||||
|
{V([]byte("bytes2")), V(MyString("bytes2"))},
|
||||||
|
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
||||||
|
{V(MyString("runes♝")), V([]rune("runes♝"))},
|
||||||
|
{V([]rune("runes♕")), V(MyString("runes♕"))},
|
||||||
|
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||||
|
{V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
||||||
|
{V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||||
|
{V(int('a')), V(MyString("a"))},
|
||||||
|
{V(int8('a')), V(MyString("a"))},
|
||||||
|
{V(int16('a')), V(MyString("a"))},
|
||||||
|
{V(int32('a')), V(MyString("a"))},
|
||||||
|
{V(int64('a')), V(MyString("a"))},
|
||||||
|
{V(uint('a')), V(MyString("a"))},
|
||||||
|
{V(uint8('a')), V(MyString("a"))},
|
||||||
|
{V(uint16('a')), V(MyString("a"))},
|
||||||
|
{V(uint32('a')), V(MyString("a"))},
|
||||||
|
{V(uint64('a')), V(MyString("a"))},
|
||||||
|
{V(uintptr('a')), V(MyString("a"))},
|
||||||
|
{V(int(-1)), V(MyString("\uFFFD"))},
|
||||||
|
{V(int8(-2)), V(MyString("\uFFFD"))},
|
||||||
|
{V(int16(-3)), V(MyString("\uFFFD"))},
|
||||||
|
{V(int32(-4)), V(MyString("\uFFFD"))},
|
||||||
|
{V(int64(-5)), V(MyString("\uFFFD"))},
|
||||||
|
{V(uint(0x110001)), V(MyString("\uFFFD"))},
|
||||||
|
{V(uint32(0x110002)), V(MyString("\uFFFD"))},
|
||||||
|
{V(uint64(0x110003)), V(MyString("\uFFFD"))},
|
||||||
|
{V(uintptr(0x110004)), V(MyString("\uFFFD"))},
|
||||||
|
|
||||||
|
// named []byte
|
||||||
|
{V(string("bytes1")), V(MyBytes("bytes1"))},
|
||||||
|
{V(MyBytes("bytes2")), V(string("bytes2"))},
|
||||||
|
{V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
|
||||||
|
{V(MyString("bytes1")), V(MyBytes("bytes1"))},
|
||||||
|
{V(MyBytes("bytes2")), V(MyString("bytes2"))},
|
||||||
|
|
||||||
|
// named []rune
|
||||||
|
{V(string("runes♝")), V(MyRunes("runes♝"))},
|
||||||
|
{V(MyRunes("runes♕")), V(string("runes♕"))},
|
||||||
|
{V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
||||||
|
{V(MyString("runes♝")), V(MyRunes("runes♝"))},
|
||||||
|
{V(MyRunes("runes♕")), V(MyString("runes♕"))},
|
||||||
|
|
||||||
|
// named types and equal underlying types
|
||||||
|
{V(new(int)), V(new(integer))},
|
||||||
|
{V(new(integer)), V(new(int))},
|
||||||
|
{V(Empty{}), V(struct{}{})},
|
||||||
|
{V(new(Empty)), V(new(struct{}))},
|
||||||
|
{V(struct{}{}), V(Empty{})},
|
||||||
|
{V(new(struct{})), V(new(Empty))},
|
||||||
|
{V(Empty{}), V(Empty{})},
|
||||||
|
{V(MyBytes{}), V([]byte{})},
|
||||||
|
{V([]byte{}), V(MyBytes{})},
|
||||||
|
{V((func())(nil)), V(MyFunc(nil))},
|
||||||
|
{V((MyFunc)(nil)), V((func())(nil))},
|
||||||
|
|
||||||
|
// can convert *byte and *MyByte
|
||||||
|
{V((*byte)(nil)), V((*MyByte)(nil))},
|
||||||
|
{V((*MyByte)(nil)), V((*byte)(nil))},
|
||||||
|
|
||||||
|
// cannot convert mismatched array sizes
|
||||||
|
{V([2]byte{}), V([2]byte{})},
|
||||||
|
{V([3]byte{}), V([3]byte{})},
|
||||||
|
|
||||||
|
// cannot convert other instances
|
||||||
|
{V((**byte)(nil)), V((**byte)(nil))},
|
||||||
|
{V((**MyByte)(nil)), V((**MyByte)(nil))},
|
||||||
|
{V((chan byte)(nil)), V((chan byte)(nil))},
|
||||||
|
{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
|
||||||
|
{V(([]byte)(nil)), V(([]byte)(nil))},
|
||||||
|
{V(([]MyByte)(nil)), V(([]MyByte)(nil))},
|
||||||
|
{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
|
||||||
|
{V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},
|
||||||
|
{V((map[byte]int)(nil)), V((map[byte]int)(nil))},
|
||||||
|
{V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},
|
||||||
|
{V([2]byte{}), V([2]byte{})},
|
||||||
|
{V([2]MyByte{}), V([2]MyByte{})},
|
||||||
|
|
||||||
|
// other
|
||||||
|
{V((***int)(nil)), V((***int)(nil))},
|
||||||
|
{V((***byte)(nil)), V((***byte)(nil))},
|
||||||
|
{V((***int32)(nil)), V((***int32)(nil))},
|
||||||
|
{V((***int64)(nil)), V((***int64)(nil))},
|
||||||
|
{V((chan int)(nil)), V((<-chan int)(nil))},
|
||||||
|
{V((chan int)(nil)), V((chan<- int)(nil))},
|
||||||
|
{V((chan string)(nil)), V((<-chan string)(nil))},
|
||||||
|
{V((chan string)(nil)), V((chan<- string)(nil))},
|
||||||
|
{V((chan byte)(nil)), V((chan byte)(nil))},
|
||||||
|
{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
|
||||||
|
{V((map[int]bool)(nil)), V((map[int]bool)(nil))},
|
||||||
|
{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
|
||||||
|
{V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},
|
||||||
|
{V([]uint(nil)), V([]uint(nil))},
|
||||||
|
{V([]int(nil)), V([]int(nil))},
|
||||||
|
{V(new(interface{})), V(new(interface{}))},
|
||||||
|
{V(new(io.Reader)), V(new(io.Reader))},
|
||||||
|
{V(new(io.Writer)), V(new(io.Writer))},
|
||||||
|
|
||||||
|
// 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 TestConvert(t *testing.T) {
|
||||||
|
canConvert := map[[2]Type]bool{}
|
||||||
|
all := map[Type]bool{}
|
||||||
|
|
||||||
|
for _, tt := range convertTests {
|
||||||
|
t1 := tt.in.Type()
|
||||||
|
if !t1.ConvertibleTo(t1) {
|
||||||
|
t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t2 := tt.out.Type()
|
||||||
|
if !t1.ConvertibleTo(t2) {
|
||||||
|
t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
all[t1] = true
|
||||||
|
all[t2] = true
|
||||||
|
canConvert[[2]Type{t1, t2}] = true
|
||||||
|
|
||||||
|
v1 := tt.in
|
||||||
|
vout1 := v1.Convert(t1)
|
||||||
|
out1 := vout1.Interface()
|
||||||
|
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
|
||||||
|
t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t1, out1, out1, tt.in.Interface(), tt.in.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
vout := v1.Convert(t2)
|
||||||
|
out := vout.Interface()
|
||||||
|
if vout.Type() != tt.out.Type() || !DeepEqual(out, tt.out.Interface()) {
|
||||||
|
t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t2, out, out, tt.out.Interface(), tt.out.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsRO(v1) {
|
||||||
|
t.Errorf("table entry %v is RO, should not be", v1)
|
||||||
|
}
|
||||||
|
if IsRO(vout1) {
|
||||||
|
t.Errorf("self-conversion output %v is RO, should not be", vout1)
|
||||||
|
}
|
||||||
|
if IsRO(vout) {
|
||||||
|
t.Errorf("conversion output %v is RO, should not be", vout)
|
||||||
|
}
|
||||||
|
if !IsRO(MakeRO(v1).Convert(t1)) {
|
||||||
|
t.Errorf("RO self-conversion output %v is not RO, should be", v1)
|
||||||
|
}
|
||||||
|
if !IsRO(MakeRO(v1).Convert(t2)) {
|
||||||
|
t.Errorf("RO conversion output %v is not RO, should be", v1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume that of all the types we saw during the tests,
|
||||||
|
// if there wasn't an explicit entry for a conversion between
|
||||||
|
// a pair of types, then it's not to be allowed. This checks for
|
||||||
|
// things like 'int64' converting to '*int'.
|
||||||
|
for t1 := range all {
|
||||||
|
for t2 := range all {
|
||||||
|
expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0
|
||||||
|
if ok := t1.ConvertibleTo(t2); ok != expectOK {
|
||||||
|
t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type B1 struct {
|
type B1 struct {
|
||||||
X int
|
X int
|
||||||
Y int
|
Y int
|
||||||
|
16
src/pkg/reflect/export_test.go
Normal file
16
src/pkg/reflect/export_test.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package reflect
|
||||||
|
|
||||||
|
// MakeRO returns a copy of v with the read-only flag set.
|
||||||
|
func MakeRO(v Value) Value {
|
||||||
|
v.flag |= flagRO
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRO reports whether v's read-only flag is set.
|
||||||
|
func IsRO(v Value) bool {
|
||||||
|
return v.flag&flagRO != 0
|
||||||
|
}
|
@ -92,6 +92,9 @@ type Type interface {
|
|||||||
// AssignableTo returns true if a value of the type is assignable to type u.
|
// AssignableTo returns true if a value of the type is assignable to type u.
|
||||||
AssignableTo(u Type) bool
|
AssignableTo(u Type) bool
|
||||||
|
|
||||||
|
// ConvertibleTo returns true if a value of the type is convertible to type u.
|
||||||
|
ConvertibleTo(u Type) bool
|
||||||
|
|
||||||
// Methods applicable only to some types, depending on Kind.
|
// Methods applicable only to some types, depending on Kind.
|
||||||
// The methods allowed for each kind are:
|
// The methods allowed for each kind are:
|
||||||
//
|
//
|
||||||
@ -1096,6 +1099,14 @@ func (t *commonType) AssignableTo(u Type) bool {
|
|||||||
return directlyAssignable(uu, t) || implements(uu, t)
|
return directlyAssignable(uu, t) || implements(uu, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *commonType) ConvertibleTo(u Type) bool {
|
||||||
|
if u == nil {
|
||||||
|
panic("reflect: nil type passed to Type.AssignableTo")
|
||||||
|
}
|
||||||
|
uu := u.(*commonType)
|
||||||
|
return convertOp(uu, t) != nil
|
||||||
|
}
|
||||||
|
|
||||||
// implements returns true if the type V implements the interface type T.
|
// implements returns true if the type V implements the interface type T.
|
||||||
func implements(T, V *commonType) bool {
|
func implements(T, V *commonType) bool {
|
||||||
if T.Kind() != Interface {
|
if T.Kind() != Interface {
|
||||||
@ -1167,10 +1178,28 @@ func directlyAssignable(T, V *commonType) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// x's type T and V have identical underlying types.
|
// x's type T and V must have identical underlying types.
|
||||||
// Since at least one is unnamed, only the composite types
|
return haveIdenticalUnderlyingType(T, V)
|
||||||
// need to be considered.
|
}
|
||||||
switch T.Kind() {
|
|
||||||
|
func haveIdenticalUnderlyingType(T, V *commonType) bool {
|
||||||
|
if T == V {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := T.Kind()
|
||||||
|
if kind != V.Kind() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-composite types of equal kind have same underlying type
|
||||||
|
// (the predefined instance of the type).
|
||||||
|
if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Composite types.
|
||||||
|
switch kind {
|
||||||
case Array:
|
case Array:
|
||||||
return T.Elem() == V.Elem() && T.Len() == V.Len()
|
return T.Elem() == V.Elem() && T.Len() == V.Len()
|
||||||
|
|
||||||
|
@ -302,6 +302,17 @@ func (v Value) Bytes() []byte {
|
|||||||
return *(*[]byte)(v.val)
|
return *(*[]byte)(v.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runes returns v's underlying value.
|
||||||
|
// It panics if v's underlying value is not a slice of runes (int32s).
|
||||||
|
func (v Value) runes() []rune {
|
||||||
|
v.mustBe(Slice)
|
||||||
|
if v.typ.Elem().Kind() != Int32 {
|
||||||
|
panic("reflect.Value.Bytes of non-rune slice")
|
||||||
|
}
|
||||||
|
// Slice is always bigger than a word; assume flagIndir.
|
||||||
|
return *(*[]rune)(v.val)
|
||||||
|
}
|
||||||
|
|
||||||
// CanAddr returns true if the value's address can be obtained with Addr.
|
// CanAddr returns true if the value's address can be obtained with Addr.
|
||||||
// Such values are called addressable. A value is addressable if it is
|
// Such values are called addressable. A value is addressable if it is
|
||||||
// an element of a slice, an element of an addressable array,
|
// an element of a slice, an element of an addressable array,
|
||||||
@ -1221,6 +1232,17 @@ func (v Value) SetBytes(x []byte) {
|
|||||||
*(*[]byte)(v.val) = x
|
*(*[]byte)(v.val) = x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setRunes sets v's underlying value.
|
||||||
|
// It panics if v's underlying value is not a slice of runes (int32s).
|
||||||
|
func (v Value) setRunes(x []rune) {
|
||||||
|
v.mustBeAssignable()
|
||||||
|
v.mustBe(Slice)
|
||||||
|
if v.typ.Elem().Kind() != Int32 {
|
||||||
|
panic("reflect.Value.setRunes of non-rune slice")
|
||||||
|
}
|
||||||
|
*(*[]rune)(v.val) = x
|
||||||
|
}
|
||||||
|
|
||||||
// SetComplex sets v's underlying value to x.
|
// SetComplex sets v's underlying value to x.
|
||||||
// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
|
// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
|
||||||
func (v Value) SetComplex(x complex128) {
|
func (v Value) SetComplex(x complex128) {
|
||||||
@ -1916,6 +1938,302 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
|
|||||||
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
|
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert returns the value v converted to type t.
|
||||||
|
// If the usual Go conversion rules do not allow conversion
|
||||||
|
// of the value v to type t, Convert panics.
|
||||||
|
func (v Value) Convert(t Type) Value {
|
||||||
|
if v.flag&flagMethod != 0 {
|
||||||
|
panic("reflect.Value.Convert: cannot convert method values")
|
||||||
|
}
|
||||||
|
op := convertOp(t.common(), v.typ)
|
||||||
|
if op == nil {
|
||||||
|
panic("reflect.Value.Convert: value of type " + v.typ.String() + " cannot be converted to type " + t.String())
|
||||||
|
}
|
||||||
|
return op(v, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp returns the function to convert a value of type src
|
||||||
|
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
|
||||||
|
func convertOp(dst, src *commonType) func(Value, Type) Value {
|
||||||
|
switch src.Kind() {
|
||||||
|
case Int, Int8, Int16, Int32, Int64:
|
||||||
|
switch dst.Kind() {
|
||||||
|
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
|
return cvtInt
|
||||||
|
case Float32, Float64:
|
||||||
|
return cvtIntFloat
|
||||||
|
case String:
|
||||||
|
return cvtIntString
|
||||||
|
}
|
||||||
|
|
||||||
|
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
|
switch dst.Kind() {
|
||||||
|
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
|
return cvtUint
|
||||||
|
case Float32, Float64:
|
||||||
|
return cvtUintFloat
|
||||||
|
case String:
|
||||||
|
return cvtUintString
|
||||||
|
}
|
||||||
|
|
||||||
|
case Float32, Float64:
|
||||||
|
switch dst.Kind() {
|
||||||
|
case Int, Int8, Int16, Int32, Int64:
|
||||||
|
return cvtFloatInt
|
||||||
|
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
|
return cvtFloatUint
|
||||||
|
case Float32, Float64:
|
||||||
|
return cvtFloat
|
||||||
|
}
|
||||||
|
|
||||||
|
case Complex64, Complex128:
|
||||||
|
switch dst.Kind() {
|
||||||
|
case Complex64, Complex128:
|
||||||
|
return cvtComplex
|
||||||
|
}
|
||||||
|
|
||||||
|
case String:
|
||||||
|
if dst.Kind() == Slice && dst.Elem().PkgPath() == "" {
|
||||||
|
switch dst.Elem().Kind() {
|
||||||
|
case Uint8:
|
||||||
|
return cvtStringBytes
|
||||||
|
case Int32:
|
||||||
|
return cvtStringRunes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case Slice:
|
||||||
|
if dst.Kind() == String && src.Elem().PkgPath() == "" {
|
||||||
|
switch src.Elem().Kind() {
|
||||||
|
case Uint8:
|
||||||
|
return cvtBytesString
|
||||||
|
case Int32:
|
||||||
|
return cvtRunesString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dst and src have same underlying type.
|
||||||
|
if haveIdenticalUnderlyingType(dst, src) {
|
||||||
|
return cvtDirect
|
||||||
|
}
|
||||||
|
|
||||||
|
// dst and src are unnamed pointer types with same underlying base type.
|
||||||
|
if dst.Kind() == Ptr && dst.Name() == "" &&
|
||||||
|
src.Kind() == Ptr && src.Name() == "" &&
|
||||||
|
haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
|
||||||
|
return cvtDirect
|
||||||
|
}
|
||||||
|
|
||||||
|
if implements(dst, src) {
|
||||||
|
if src.Kind() == Interface {
|
||||||
|
return cvtI2I
|
||||||
|
}
|
||||||
|
return cvtT2I
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeInt returns a Value of type t equal to bits (possibly truncated),
|
||||||
|
// where t is a signed or unsigned int type.
|
||||||
|
func makeInt(f flag, bits uint64, t Type) Value {
|
||||||
|
typ := t.common()
|
||||||
|
if typ.size > ptrSize {
|
||||||
|
// Assume ptrSize >= 4, so this must be uint64.
|
||||||
|
ptr := unsafe_New(t)
|
||||||
|
*(*uint64)(unsafe.Pointer(ptr)) = bits
|
||||||
|
return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
var w iword
|
||||||
|
switch typ.size {
|
||||||
|
case 1:
|
||||||
|
*(*uint8)(unsafe.Pointer(&w)) = uint8(bits)
|
||||||
|
case 2:
|
||||||
|
*(*uint16)(unsafe.Pointer(&w)) = uint16(bits)
|
||||||
|
case 4:
|
||||||
|
*(*uint32)(unsafe.Pointer(&w)) = uint32(bits)
|
||||||
|
case 8:
|
||||||
|
*(*uint64)(unsafe.Pointer(&w)) = uint64(bits)
|
||||||
|
}
|
||||||
|
return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
|
||||||
|
// where t is a float32 or float64 type.
|
||||||
|
func makeFloat(f flag, v float64, t Type) Value {
|
||||||
|
typ := t.common()
|
||||||
|
if typ.size > ptrSize {
|
||||||
|
// Assume ptrSize >= 4, so this must be float64.
|
||||||
|
ptr := unsafe_New(t)
|
||||||
|
*(*float64)(unsafe.Pointer(ptr)) = v
|
||||||
|
return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
var w iword
|
||||||
|
switch typ.size {
|
||||||
|
case 4:
|
||||||
|
*(*float32)(unsafe.Pointer(&w)) = float32(v)
|
||||||
|
case 8:
|
||||||
|
*(*float64)(unsafe.Pointer(&w)) = v
|
||||||
|
}
|
||||||
|
return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
|
||||||
|
// where t is a complex64 or complex128 type.
|
||||||
|
func makeComplex(f flag, v complex128, t Type) Value {
|
||||||
|
typ := t.common()
|
||||||
|
if typ.size > ptrSize {
|
||||||
|
ptr := unsafe_New(t)
|
||||||
|
switch typ.size {
|
||||||
|
case 8:
|
||||||
|
*(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
|
||||||
|
case 16:
|
||||||
|
*(*complex128)(unsafe.Pointer(ptr)) = v
|
||||||
|
}
|
||||||
|
return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume ptrSize <= 8 so this must be complex64.
|
||||||
|
var w iword
|
||||||
|
*(*complex64)(unsafe.Pointer(&w)) = complex64(v)
|
||||||
|
return Value{typ, unsafe.Pointer(w), f | flag(typ.Kind())<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeString(f flag, v string, t Type) Value {
|
||||||
|
ret := New(t).Elem()
|
||||||
|
ret.SetString(v)
|
||||||
|
ret.flag = ret.flag&^flagAddr | f
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeBytes(f flag, v []byte, t Type) Value {
|
||||||
|
ret := New(t).Elem()
|
||||||
|
ret.SetBytes(v)
|
||||||
|
ret.flag = ret.flag&^flagAddr | f
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeRunes(f flag, v []rune, t Type) Value {
|
||||||
|
ret := New(t).Elem()
|
||||||
|
ret.setRunes(v)
|
||||||
|
ret.flag = ret.flag&^flagAddr | f
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// These conversion functions are returned by convertOp
|
||||||
|
// for classes of conversions. For example, the first function, cvtInt,
|
||||||
|
// takes any value v of signed int type and returns the value converted
|
||||||
|
// to type t, where t is any signed or unsigned int type.
|
||||||
|
|
||||||
|
// convertOp: intXX -> [u]intXX
|
||||||
|
func cvtInt(v Value, t Type) Value {
|
||||||
|
return makeInt(v.flag&flagRO, uint64(v.Int()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: uintXX -> [u]intXX
|
||||||
|
func cvtUint(v Value, t Type) Value {
|
||||||
|
return makeInt(v.flag&flagRO, v.Uint(), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: floatXX -> intXX
|
||||||
|
func cvtFloatInt(v Value, t Type) Value {
|
||||||
|
return makeInt(v.flag&flagRO, uint64(int64(v.Float())), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: floatXX -> uintXX
|
||||||
|
func cvtFloatUint(v Value, t Type) Value {
|
||||||
|
return makeInt(v.flag&flagRO, uint64(v.Float()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: intXX -> floatXX
|
||||||
|
func cvtIntFloat(v Value, t Type) Value {
|
||||||
|
return makeFloat(v.flag&flagRO, float64(v.Int()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: uintXX -> floatXX
|
||||||
|
func cvtUintFloat(v Value, t Type) Value {
|
||||||
|
return makeFloat(v.flag&flagRO, float64(v.Uint()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: floatXX -> floatXX
|
||||||
|
func cvtFloat(v Value, t Type) Value {
|
||||||
|
return makeFloat(v.flag&flagRO, v.Float(), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: complexXX -> complexXX
|
||||||
|
func cvtComplex(v Value, t Type) Value {
|
||||||
|
return makeComplex(v.flag&flagRO, v.Complex(), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: intXX -> string
|
||||||
|
func cvtIntString(v Value, t Type) Value {
|
||||||
|
return makeString(v.flag&flagRO, string(v.Int()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: uintXX -> string
|
||||||
|
func cvtUintString(v Value, t Type) Value {
|
||||||
|
return makeString(v.flag&flagRO, string(v.Uint()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: []byte -> string
|
||||||
|
func cvtBytesString(v Value, t Type) Value {
|
||||||
|
return makeString(v.flag&flagRO, string(v.Bytes()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: string -> []byte
|
||||||
|
func cvtStringBytes(v Value, t Type) Value {
|
||||||
|
return makeBytes(v.flag&flagRO, []byte(v.String()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: []rune -> string
|
||||||
|
func cvtRunesString(v Value, t Type) Value {
|
||||||
|
return makeString(v.flag&flagRO, string(v.runes()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: string -> []rune
|
||||||
|
func cvtStringRunes(v Value, t Type) Value {
|
||||||
|
return makeRunes(v.flag&flagRO, []rune(v.String()), t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: direct copy
|
||||||
|
func cvtDirect(v Value, typ Type) Value {
|
||||||
|
f := v.flag
|
||||||
|
t := typ.common()
|
||||||
|
val := v.val
|
||||||
|
if f&flagAddr != 0 {
|
||||||
|
// indirect, mutable word - make a copy
|
||||||
|
ptr := unsafe_New(t)
|
||||||
|
memmove(ptr, val, t.size)
|
||||||
|
val = ptr
|
||||||
|
f &^= flagAddr
|
||||||
|
}
|
||||||
|
return Value{t, val, v.flag&flagRO | f}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: concrete -> interface
|
||||||
|
func cvtT2I(v Value, typ Type) Value {
|
||||||
|
target := new(interface{})
|
||||||
|
x := valueInterface(v, false)
|
||||||
|
if typ.NumMethod() == 0 {
|
||||||
|
*target = x
|
||||||
|
} else {
|
||||||
|
ifaceE2I(typ.runtimeType(), x, unsafe.Pointer(target))
|
||||||
|
}
|
||||||
|
return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertOp: interface -> interface
|
||||||
|
func cvtI2I(v Value, typ Type) Value {
|
||||||
|
if v.IsNil() {
|
||||||
|
ret := Zero(typ)
|
||||||
|
ret.flag |= v.flag & flagRO
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
return cvtT2I(v.Elem(), typ)
|
||||||
|
}
|
||||||
|
|
||||||
// implemented in ../pkg/runtime
|
// implemented in ../pkg/runtime
|
||||||
func chancap(ch iword) int32
|
func chancap(ch iword) int32
|
||||||
func chanclose(ch iword)
|
func chanclose(ch iword)
|
||||||
|
Loading…
Reference in New Issue
Block a user