summaryrefslogtreecommitdiff
path: root/src/pkg/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/reflect')
-rw-r--r--src/pkg/reflect/all_test.go3841
-rw-r--r--src/pkg/reflect/asm_386.s27
-rw-r--r--src/pkg/reflect/asm_amd64.s27
-rw-r--r--src/pkg/reflect/asm_amd64p32.s27
-rw-r--r--src/pkg/reflect/asm_arm.s27
-rw-r--r--src/pkg/reflect/deepequal.go145
-rw-r--r--src/pkg/reflect/example_test.go66
-rw-r--r--src/pkg/reflect/export_test.go19
-rw-r--r--src/pkg/reflect/makefunc.go120
-rw-r--r--src/pkg/reflect/set_test.go211
-rw-r--r--src/pkg/reflect/tostring_test.go95
-rw-r--r--src/pkg/reflect/type.go1926
-rw-r--r--src/pkg/reflect/value.go2684
13 files changed, 0 insertions, 9215 deletions
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
deleted file mode 100644
index e9949012c..000000000
--- a/src/pkg/reflect/all_test.go
+++ /dev/null
@@ -1,3841 +0,0 @@
-// Copyright 2009 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_test
-
-import (
- "bytes"
- "encoding/base64"
- "flag"
- "fmt"
- "io"
- "math/rand"
- "os"
- . "reflect"
- "runtime"
- "sort"
- "strings"
- "sync"
- "testing"
- "time"
- "unsafe"
-)
-
-func TestBool(t *testing.T) {
- v := ValueOf(true)
- if v.Bool() != true {
- t.Fatal("ValueOf(true).Bool() = false")
- }
-}
-
-type integer int
-type T struct {
- a int
- b float64
- c string
- d *int
-}
-
-type pair struct {
- i interface{}
- s string
-}
-
-func isDigit(c uint8) bool { return '0' <= c && c <= '9' }
-
-func assert(t *testing.T, s, want string) {
- if s != want {
- t.Errorf("have %#q want %#q", s, want)
- }
-}
-
-func typestring(i interface{}) string { return TypeOf(i).String() }
-
-var typeTests = []pair{
- {struct{ x int }{}, "int"},
- {struct{ x int8 }{}, "int8"},
- {struct{ x int16 }{}, "int16"},
- {struct{ x int32 }{}, "int32"},
- {struct{ x int64 }{}, "int64"},
- {struct{ x uint }{}, "uint"},
- {struct{ x uint8 }{}, "uint8"},
- {struct{ x uint16 }{}, "uint16"},
- {struct{ x uint32 }{}, "uint32"},
- {struct{ x uint64 }{}, "uint64"},
- {struct{ x float32 }{}, "float32"},
- {struct{ x float64 }{}, "float64"},
- {struct{ x int8 }{}, "int8"},
- {struct{ x (**int8) }{}, "**int8"},
- {struct{ x (**integer) }{}, "**reflect_test.integer"},
- {struct{ x ([32]int32) }{}, "[32]int32"},
- {struct{ x ([]int8) }{}, "[]int8"},
- {struct{ x (map[string]int32) }{}, "map[string]int32"},
- {struct{ x (chan<- string) }{}, "chan<- string"},
- {struct {
- x struct {
- c chan *int32
- d float32
- }
- }{},
- "struct { c chan *int32; d float32 }",
- },
- {struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
- {struct {
- x struct {
- c func(chan *integer, *int8)
- }
- }{},
- "struct { c func(chan *reflect_test.integer, *int8) }",
- },
- {struct {
- x struct {
- a int8
- b int32
- }
- }{},
- "struct { a int8; b int32 }",
- },
- {struct {
- x struct {
- a int8
- b int8
- c int32
- }
- }{},
- "struct { a int8; b int8; c int32 }",
- },
- {struct {
- x struct {
- a int8
- b int8
- c int8
- d int32
- }
- }{},
- "struct { a int8; b int8; c int8; d int32 }",
- },
- {struct {
- x struct {
- a int8
- b int8
- c int8
- d int8
- e int32
- }
- }{},
- "struct { a int8; b int8; c int8; d int8; e int32 }",
- },
- {struct {
- x struct {
- a int8
- b int8
- c int8
- d int8
- e int8
- f int32
- }
- }{},
- "struct { a int8; b int8; c int8; d int8; e int8; f int32 }",
- },
- {struct {
- x struct {
- a int8 `reflect:"hi there"`
- }
- }{},
- `struct { a int8 "reflect:\"hi there\"" }`,
- },
- {struct {
- x struct {
- a int8 `reflect:"hi \x00there\t\n\"\\"`
- }
- }{},
- `struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`,
- },
- {struct {
- x struct {
- f func(args ...int)
- }
- }{},
- "struct { f func(...int) }",
- },
- {struct {
- x (interface {
- a(func(func(int) int) func(func(int)) int)
- b()
- })
- }{},
- "interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }",
- },
-}
-
-var valueTests = []pair{
- {new(int), "132"},
- {new(int8), "8"},
- {new(int16), "16"},
- {new(int32), "32"},
- {new(int64), "64"},
- {new(uint), "132"},
- {new(uint8), "8"},
- {new(uint16), "16"},
- {new(uint32), "32"},
- {new(uint64), "64"},
- {new(float32), "256.25"},
- {new(float64), "512.125"},
- {new(complex64), "532.125+10i"},
- {new(complex128), "564.25+1i"},
- {new(string), "stringy cheese"},
- {new(bool), "true"},
- {new(*int8), "*int8(0)"},
- {new(**int8), "**int8(0)"},
- {new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
- {new(**integer), "**reflect_test.integer(0)"},
- {new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
- {new(chan<- string), "chan<- string"},
- {new(func(a int8, b int32)), "func(int8, int32)(0)"},
- {new(struct {
- c chan *int32
- d float32
- }),
- "struct { c chan *int32; d float32 }{chan *int32, 0}",
- },
- {new(struct{ c func(chan *integer, *int8) }),
- "struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}",
- },
- {new(struct {
- a int8
- b int32
- }),
- "struct { a int8; b int32 }{0, 0}",
- },
- {new(struct {
- a int8
- b int8
- c int32
- }),
- "struct { a int8; b int8; c int32 }{0, 0, 0}",
- },
-}
-
-func testType(t *testing.T, i int, typ Type, want string) {
- s := typ.String()
- if s != want {
- t.Errorf("#%d: have %#q, want %#q", i, s, want)
- }
-}
-
-func TestTypes(t *testing.T) {
- for i, tt := range typeTests {
- testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s)
- }
-}
-
-func TestSet(t *testing.T) {
- for i, tt := range valueTests {
- v := ValueOf(tt.i)
- v = v.Elem()
- switch v.Kind() {
- case Int:
- v.SetInt(132)
- case Int8:
- v.SetInt(8)
- case Int16:
- v.SetInt(16)
- case Int32:
- v.SetInt(32)
- case Int64:
- v.SetInt(64)
- case Uint:
- v.SetUint(132)
- case Uint8:
- v.SetUint(8)
- case Uint16:
- v.SetUint(16)
- case Uint32:
- v.SetUint(32)
- case Uint64:
- v.SetUint(64)
- case Float32:
- v.SetFloat(256.25)
- case Float64:
- v.SetFloat(512.125)
- case Complex64:
- v.SetComplex(532.125 + 10i)
- case Complex128:
- v.SetComplex(564.25 + 1i)
- case String:
- v.SetString("stringy cheese")
- case Bool:
- v.SetBool(true)
- }
- s := valueToString(v)
- if s != tt.s {
- t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
- }
- }
-}
-
-func TestSetValue(t *testing.T) {
- for i, tt := range valueTests {
- v := ValueOf(tt.i).Elem()
- switch v.Kind() {
- case Int:
- v.Set(ValueOf(int(132)))
- case Int8:
- v.Set(ValueOf(int8(8)))
- case Int16:
- v.Set(ValueOf(int16(16)))
- case Int32:
- v.Set(ValueOf(int32(32)))
- case Int64:
- v.Set(ValueOf(int64(64)))
- case Uint:
- v.Set(ValueOf(uint(132)))
- case Uint8:
- v.Set(ValueOf(uint8(8)))
- case Uint16:
- v.Set(ValueOf(uint16(16)))
- case Uint32:
- v.Set(ValueOf(uint32(32)))
- case Uint64:
- v.Set(ValueOf(uint64(64)))
- case Float32:
- v.Set(ValueOf(float32(256.25)))
- case Float64:
- v.Set(ValueOf(512.125))
- case Complex64:
- v.Set(ValueOf(complex64(532.125 + 10i)))
- case Complex128:
- v.Set(ValueOf(complex128(564.25 + 1i)))
- case String:
- v.Set(ValueOf("stringy cheese"))
- case Bool:
- v.Set(ValueOf(true))
- }
- s := valueToString(v)
- if s != tt.s {
- t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
- }
- }
-}
-
-var _i = 7
-
-var valueToStringTests = []pair{
- {123, "123"},
- {123.5, "123.5"},
- {byte(123), "123"},
- {"abc", "abc"},
- {T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"},
- {new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"},
- {[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
- {&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
- {[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
- {&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
-}
-
-func TestValueToString(t *testing.T) {
- for i, test := range valueToStringTests {
- s := valueToString(ValueOf(test.i))
- if s != test.s {
- t.Errorf("#%d: have %#q, want %#q", i, s, test.s)
- }
- }
-}
-
-func TestArrayElemSet(t *testing.T) {
- v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem()
- v.Index(4).SetInt(123)
- s := valueToString(v)
- const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
- if s != want {
- t.Errorf("[10]int: have %#q want %#q", s, want)
- }
-
- v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
- v.Index(4).SetInt(123)
- s = valueToString(v)
- const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
- if s != want1 {
- t.Errorf("[]int: have %#q want %#q", s, want1)
- }
-}
-
-func TestPtrPointTo(t *testing.T) {
- var ip *int32
- var i int32 = 1234
- vip := ValueOf(&ip)
- vi := ValueOf(&i).Elem()
- vip.Elem().Set(vi.Addr())
- if *ip != 1234 {
- t.Errorf("got %d, want 1234", *ip)
- }
-
- ip = nil
- vp := ValueOf(&ip).Elem()
- vp.Set(Zero(vp.Type()))
- if ip != nil {
- t.Errorf("got non-nil (%p), want nil", ip)
- }
-}
-
-func TestPtrSetNil(t *testing.T) {
- var i int32 = 1234
- ip := &i
- vip := ValueOf(&ip)
- vip.Elem().Set(Zero(vip.Elem().Type()))
- if ip != nil {
- t.Errorf("got non-nil (%d), want nil", *ip)
- }
-}
-
-func TestMapSetNil(t *testing.T) {
- m := make(map[string]int)
- vm := ValueOf(&m)
- vm.Elem().Set(Zero(vm.Elem().Type()))
- if m != nil {
- t.Errorf("got non-nil (%p), want nil", m)
- }
-}
-
-func TestAll(t *testing.T) {
- testType(t, 1, TypeOf((int8)(0)), "int8")
- testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8")
-
- typ := TypeOf((*struct {
- c chan *int32
- d float32
- })(nil))
- testType(t, 3, typ, "*struct { c chan *int32; d float32 }")
- etyp := typ.Elem()
- testType(t, 4, etyp, "struct { c chan *int32; d float32 }")
- styp := etyp
- f := styp.Field(0)
- testType(t, 5, f.Type, "chan *int32")
-
- f, present := styp.FieldByName("d")
- if !present {
- t.Errorf("FieldByName says present field is absent")
- }
- testType(t, 6, f.Type, "float32")
-
- f, present = styp.FieldByName("absent")
- if present {
- t.Errorf("FieldByName says absent field is present")
- }
-
- typ = TypeOf([32]int32{})
- testType(t, 7, typ, "[32]int32")
- testType(t, 8, typ.Elem(), "int32")
-
- typ = TypeOf((map[string]*int32)(nil))
- testType(t, 9, typ, "map[string]*int32")
- mtyp := typ
- testType(t, 10, mtyp.Key(), "string")
- testType(t, 11, mtyp.Elem(), "*int32")
-
- typ = TypeOf((chan<- string)(nil))
- testType(t, 12, typ, "chan<- string")
- testType(t, 13, typ.Elem(), "string")
-
- // make sure tag strings are not part of element type
- typ = TypeOf(struct {
- d []uint32 `reflect:"TAG"`
- }{}).Field(0).Type
- testType(t, 14, typ, "[]uint32")
-}
-
-func TestInterfaceGet(t *testing.T) {
- var inter struct {
- E interface{}
- }
- inter.E = 123.456
- v1 := ValueOf(&inter)
- v2 := v1.Elem().Field(0)
- assert(t, v2.Type().String(), "interface {}")
- i2 := v2.Interface()
- v3 := ValueOf(i2)
- assert(t, v3.Type().String(), "float64")
-}
-
-func TestInterfaceValue(t *testing.T) {
- var inter struct {
- E interface{}
- }
- inter.E = 123.456
- v1 := ValueOf(&inter)
- v2 := v1.Elem().Field(0)
- assert(t, v2.Type().String(), "interface {}")
- v3 := v2.Elem()
- assert(t, v3.Type().String(), "float64")
-
- i3 := v2.Interface()
- if _, ok := i3.(float64); !ok {
- t.Error("v2.Interface() did not return float64, got ", TypeOf(i3))
- }
-}
-
-func TestFunctionValue(t *testing.T) {
- var x interface{} = func() {}
- v := ValueOf(x)
- if fmt.Sprint(v.Interface()) != fmt.Sprint(x) {
- t.Fatalf("TestFunction returned wrong pointer")
- }
- assert(t, v.Type().String(), "func()")
-}
-
-var appendTests = []struct {
- orig, extra []int
-}{
- {make([]int, 2, 4), []int{22}},
- {make([]int, 2, 4), []int{22, 33, 44}},
-}
-
-func sameInts(x, y []int) bool {
- if len(x) != len(y) {
- return false
- }
- for i, xx := range x {
- if xx != y[i] {
- return false
- }
- }
- return true
-}
-
-func TestAppend(t *testing.T) {
- for i, test := range appendTests {
- origLen, extraLen := len(test.orig), len(test.extra)
- want := append(test.orig, test.extra...)
- // Convert extra from []int to []Value.
- e0 := make([]Value, len(test.extra))
- for j, e := range test.extra {
- e0[j] = ValueOf(e)
- }
- // Convert extra from []int to *SliceValue.
- e1 := ValueOf(test.extra)
- // Test Append.
- a0 := ValueOf(test.orig)
- have0 := Append(a0, e0...).Interface().([]int)
- if !sameInts(have0, want) {
- t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0)
- }
- // Check that the orig and extra slices were not modified.
- if len(test.orig) != origLen {
- t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
- }
- if len(test.extra) != extraLen {
- t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
- }
- // Test AppendSlice.
- a1 := ValueOf(test.orig)
- have1 := AppendSlice(a1, e1).Interface().([]int)
- if !sameInts(have1, want) {
- t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
- }
- // Check that the orig and extra slices were not modified.
- if len(test.orig) != origLen {
- t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
- }
- if len(test.extra) != extraLen {
- t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
- }
- }
-}
-
-func TestCopy(t *testing.T) {
- a := []int{1, 2, 3, 4, 10, 9, 8, 7}
- b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
- c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
- for i := 0; i < len(b); i++ {
- if b[i] != c[i] {
- t.Fatalf("b != c before test")
- }
- }
- a1 := a
- b1 := b
- aa := ValueOf(&a1).Elem()
- ab := ValueOf(&b1).Elem()
- for tocopy := 1; tocopy <= 7; tocopy++ {
- aa.SetLen(tocopy)
- Copy(ab, aa)
- aa.SetLen(8)
- for i := 0; i < tocopy; i++ {
- if a[i] != b[i] {
- t.Errorf("(i) tocopy=%d a[%d]=%d, b[%d]=%d",
- tocopy, i, a[i], i, b[i])
- }
- }
- for i := tocopy; i < len(b); i++ {
- if b[i] != c[i] {
- if i < len(a) {
- t.Errorf("(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d",
- tocopy, i, a[i], i, b[i], i, c[i])
- } else {
- t.Errorf("(iii) tocopy=%d b[%d]=%d, c[%d]=%d",
- tocopy, i, b[i], i, c[i])
- }
- } else {
- t.Logf("tocopy=%d elem %d is okay\n", tocopy, i)
- }
- }
- }
-}
-
-func TestCopyArray(t *testing.T) {
- a := [8]int{1, 2, 3, 4, 10, 9, 8, 7}
- b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
- c := b
- aa := ValueOf(&a).Elem()
- ab := ValueOf(&b).Elem()
- Copy(ab, aa)
- for i := 0; i < len(a); i++ {
- if a[i] != b[i] {
- t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i])
- }
- }
- for i := len(a); i < len(b); i++ {
- if b[i] != c[i] {
- t.Errorf("(ii) b[%d]=%d, c[%d]=%d", i, b[i], i, c[i])
- } else {
- t.Logf("elem %d is okay\n", i)
- }
- }
-}
-
-func TestBigUnnamedStruct(t *testing.T) {
- b := struct{ a, b, c, d int64 }{1, 2, 3, 4}
- v := ValueOf(b)
- b1 := v.Interface().(struct {
- a, b, c, d int64
- })
- if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {
- t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1)
- }
-}
-
-type big struct {
- a, b, c, d, e int64
-}
-
-func TestBigStruct(t *testing.T) {
- b := big{1, 2, 3, 4, 5}
- v := ValueOf(b)
- b1 := v.Interface().(big)
- if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {
- t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1)
- }
-}
-
-type Basic struct {
- x int
- y float32
-}
-
-type NotBasic Basic
-
-type DeepEqualTest struct {
- a, b interface{}
- eq bool
-}
-
-// Simple functions for DeepEqual tests.
-var (
- fn1 func() // nil.
- fn2 func() // nil.
- fn3 = func() { fn1() } // Not nil.
-)
-
-var deepEqualTests = []DeepEqualTest{
- // Equalities
- {nil, nil, true},
- {1, 1, true},
- {int32(1), int32(1), true},
- {0.5, 0.5, true},
- {float32(0.5), float32(0.5), true},
- {"hello", "hello", true},
- {make([]int, 10), make([]int, 10), true},
- {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
- {Basic{1, 0.5}, Basic{1, 0.5}, true},
- {error(nil), error(nil), true},
- {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
- {fn1, fn2, true},
-
- // Inequalities
- {1, 2, false},
- {int32(1), int32(2), false},
- {0.5, 0.6, false},
- {float32(0.5), float32(0.6), false},
- {"hello", "hey", false},
- {make([]int, 10), make([]int, 11), false},
- {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
- {Basic{1, 0.5}, Basic{1, 0.6}, false},
- {Basic{1, 0}, Basic{2, 0}, false},
- {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
- {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
- {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
- {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
- {nil, 1, false},
- {1, nil, false},
- {fn1, fn3, false},
- {fn3, fn3, false},
- {[][]int{[]int{1}}, [][]int{[]int{2}}, false},
-
- // Nil vs empty: not the same.
- {[]int{}, []int(nil), false},
- {[]int{}, []int{}, true},
- {[]int(nil), []int(nil), true},
- {map[int]int{}, map[int]int(nil), false},
- {map[int]int{}, map[int]int{}, true},
- {map[int]int(nil), map[int]int(nil), true},
-
- // Mismatched types
- {1, 1.0, false},
- {int32(1), int64(1), false},
- {0.5, "hello", false},
- {[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
- {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
- {Basic{1, 0.5}, NotBasic{1, 0.5}, false},
- {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
-}
-
-func TestDeepEqual(t *testing.T) {
- for _, test := range deepEqualTests {
- if r := DeepEqual(test.a, test.b); r != test.eq {
- t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq)
- }
- }
-}
-
-func TestTypeOf(t *testing.T) {
- // Special case for nil
- if typ := TypeOf(nil); typ != nil {
- t.Errorf("expected nil type for nil value; got %v", typ)
- }
- for _, test := range deepEqualTests {
- v := ValueOf(test.a)
- if !v.IsValid() {
- continue
- }
- typ := TypeOf(test.a)
- if typ != v.Type() {
- t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type())
- }
- }
-}
-
-type Recursive struct {
- x int
- r *Recursive
-}
-
-func TestDeepEqualRecursiveStruct(t *testing.T) {
- a, b := new(Recursive), new(Recursive)
- *a = Recursive{12, a}
- *b = Recursive{12, b}
- if !DeepEqual(a, b) {
- t.Error("DeepEqual(recursive same) = false, want true")
- }
-}
-
-type _Complex struct {
- a int
- b [3]*_Complex
- c *string
- d map[float64]float64
-}
-
-func TestDeepEqualComplexStruct(t *testing.T) {
- m := make(map[float64]float64)
- stra, strb := "hello", "hello"
- a, b := new(_Complex), new(_Complex)
- *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
- *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
- if !DeepEqual(a, b) {
- t.Error("DeepEqual(complex same) = false, want true")
- }
-}
-
-func TestDeepEqualComplexStructInequality(t *testing.T) {
- m := make(map[float64]float64)
- stra, strb := "hello", "helloo" // Difference is here
- a, b := new(_Complex), new(_Complex)
- *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
- *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
- if DeepEqual(a, b) {
- t.Error("DeepEqual(complex different) = true, want false")
- }
-}
-
-type UnexpT struct {
- m map[int]int
-}
-
-func TestDeepEqualUnexportedMap(t *testing.T) {
- // Check that DeepEqual can look at unexported fields.
- x1 := UnexpT{map[int]int{1: 2}}
- x2 := UnexpT{map[int]int{1: 2}}
- if !DeepEqual(&x1, &x2) {
- t.Error("DeepEqual(x1, x2) = false, want true")
- }
-
- y1 := UnexpT{map[int]int{2: 3}}
- if DeepEqual(&x1, &y1) {
- t.Error("DeepEqual(x1, y1) = true, want false")
- }
-}
-
-func check2ndField(x interface{}, offs uintptr, t *testing.T) {
- s := ValueOf(x)
- f := s.Type().Field(1)
- if f.Offset != offs {
- t.Error("mismatched offsets in structure alignment:", f.Offset, offs)
- }
-}
-
-// Check that structure alignment & offsets viewed through reflect agree with those
-// from the compiler itself.
-func TestAlignment(t *testing.T) {
- type T1inner struct {
- a int
- }
- type T1 struct {
- T1inner
- f int
- }
- type T2inner struct {
- a, b int
- }
- type T2 struct {
- T2inner
- f int
- }
-
- x := T1{T1inner{2}, 17}
- check2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t)
-
- x1 := T2{T2inner{2, 3}, 17}
- check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t)
-}
-
-func Nil(a interface{}, t *testing.T) {
- n := ValueOf(a).Field(0)
- if !n.IsNil() {
- t.Errorf("%v should be nil", a)
- }
-}
-
-func NotNil(a interface{}, t *testing.T) {
- n := ValueOf(a).Field(0)
- if n.IsNil() {
- t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String())
- }
-}
-
-func TestIsNil(t *testing.T) {
- // These implement IsNil.
- // Wrap in extra struct to hide interface type.
- doNil := []interface{}{
- struct{ x *int }{},
- struct{ x interface{} }{},
- struct{ x map[string]int }{},
- struct{ x func() bool }{},
- struct{ x chan int }{},
- struct{ x []string }{},
- }
- for _, ts := range doNil {
- ty := TypeOf(ts).Field(0).Type
- v := Zero(ty)
- v.IsNil() // panics if not okay to call
- }
-
- // Check the implementations
- var pi struct {
- x *int
- }
- Nil(pi, t)
- pi.x = new(int)
- NotNil(pi, t)
-
- var si struct {
- x []int
- }
- Nil(si, t)
- si.x = make([]int, 10)
- NotNil(si, t)
-
- var ci struct {
- x chan int
- }
- Nil(ci, t)
- ci.x = make(chan int)
- NotNil(ci, t)
-
- var mi struct {
- x map[int]int
- }
- Nil(mi, t)
- mi.x = make(map[int]int)
- NotNil(mi, t)
-
- var ii struct {
- x interface{}
- }
- Nil(ii, t)
- ii.x = 2
- NotNil(ii, t)
-
- var fi struct {
- x func(t *testing.T)
- }
- Nil(fi, t)
- fi.x = TestIsNil
- NotNil(fi, t)
-}
-
-func TestInterfaceExtraction(t *testing.T) {
- var s struct {
- W io.Writer
- }
-
- s.W = os.Stdout
- v := Indirect(ValueOf(&s)).Field(0).Interface()
- if v != s.W.(interface{}) {
- t.Error("Interface() on interface: ", v, s.W)
- }
-}
-
-func TestNilPtrValueSub(t *testing.T) {
- var pi *int
- if pv := ValueOf(pi); pv.Elem().IsValid() {
- t.Error("ValueOf((*int)(nil)).Elem().IsValid()")
- }
-}
-
-func TestMap(t *testing.T) {
- m := map[string]int{"a": 1, "b": 2}
- mv := ValueOf(m)
- if n := mv.Len(); n != len(m) {
- t.Errorf("Len = %d, want %d", n, len(m))
- }
- keys := mv.MapKeys()
- newmap := MakeMap(mv.Type())
- for k, v := range m {
- // Check that returned Keys match keys in range.
- // These aren't required to be in the same order.
- seen := false
- for _, kv := range keys {
- if kv.String() == k {
- seen = true
- break
- }
- }
- if !seen {
- t.Errorf("Missing key %q", k)
- }
-
- // Check that value lookup is correct.
- vv := mv.MapIndex(ValueOf(k))
- if vi := vv.Int(); vi != int64(v) {
- t.Errorf("Key %q: have value %d, want %d", k, vi, v)
- }
-
- // Copy into new map.
- newmap.SetMapIndex(ValueOf(k), ValueOf(v))
- }
- vv := mv.MapIndex(ValueOf("not-present"))
- if vv.IsValid() {
- t.Errorf("Invalid key: got non-nil value %s", valueToString(vv))
- }
-
- newm := newmap.Interface().(map[string]int)
- if len(newm) != len(m) {
- t.Errorf("length after copy: newm=%d, m=%d", len(newm), len(m))
- }
-
- for k, v := range newm {
- mv, ok := m[k]
- if mv != v {
- t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok)
- }
- }
-
- newmap.SetMapIndex(ValueOf("a"), Value{})
- v, ok := newm["a"]
- if ok {
- t.Errorf("newm[\"a\"] = %d after delete", v)
- }
-
- mv = ValueOf(&m).Elem()
- mv.Set(Zero(mv.Type()))
- if m != nil {
- t.Errorf("mv.Set(nil) failed")
- }
-}
-
-func TestNilMap(t *testing.T) {
- var m map[string]int
- mv := ValueOf(m)
- keys := mv.MapKeys()
- if len(keys) != 0 {
- t.Errorf(">0 keys for nil map: %v", keys)
- }
-
- // Check that value for missing key is zero.
- x := mv.MapIndex(ValueOf("hello"))
- if x.Kind() != Invalid {
- t.Errorf("m.MapIndex(\"hello\") for nil map = %v, want Invalid Value", x)
- }
-
- // Check big value too.
- var mbig map[string][10 << 20]byte
- x = ValueOf(mbig).MapIndex(ValueOf("hello"))
- if x.Kind() != Invalid {
- t.Errorf("mbig.MapIndex(\"hello\") for nil map = %v, want Invalid Value", x)
- }
-
- // Test that deletes from a nil map succeed.
- mv.SetMapIndex(ValueOf("hi"), Value{})
-}
-
-func TestChan(t *testing.T) {
- for loop := 0; loop < 2; loop++ {
- var c chan int
- var cv Value
-
- // check both ways to allocate channels
- switch loop {
- case 1:
- c = make(chan int, 1)
- cv = ValueOf(c)
- case 0:
- cv = MakeChan(TypeOf(c), 1)
- c = cv.Interface().(chan int)
- }
-
- // Send
- cv.Send(ValueOf(2))
- if i := <-c; i != 2 {
- t.Errorf("reflect Send 2, native recv %d", i)
- }
-
- // Recv
- c <- 3
- if i, ok := cv.Recv(); i.Int() != 3 || !ok {
- t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok)
- }
-
- // TryRecv fail
- val, ok := cv.TryRecv()
- if val.IsValid() || ok {
- t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok)
- }
-
- // TryRecv success
- c <- 4
- val, ok = cv.TryRecv()
- if !val.IsValid() {
- t.Errorf("TryRecv on ready chan got nil")
- } else if i := val.Int(); i != 4 || !ok {
- t.Errorf("native send 4, TryRecv %d, %t", i, ok)
- }
-
- // TrySend fail
- c <- 100
- ok = cv.TrySend(ValueOf(5))
- i := <-c
- if ok {
- t.Errorf("TrySend on full chan succeeded: value %d", i)
- }
-
- // TrySend success
- ok = cv.TrySend(ValueOf(6))
- if !ok {
- t.Errorf("TrySend on empty chan failed")
- } else {
- if i = <-c; i != 6 {
- t.Errorf("TrySend 6, recv %d", i)
- }
- }
-
- // Close
- c <- 123
- cv.Close()
- if i, ok := cv.Recv(); i.Int() != 123 || !ok {
- t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok)
- }
- if i, ok := cv.Recv(); i.Int() != 0 || ok {
- t.Errorf("after close Recv %d, %t", i.Int(), ok)
- }
- }
-
- // check creation of unbuffered channel
- var c chan int
- cv := MakeChan(TypeOf(c), 0)
- c = cv.Interface().(chan int)
- if cv.TrySend(ValueOf(7)) {
- t.Errorf("TrySend on sync chan succeeded")
- }
- if v, ok := cv.TryRecv(); v.IsValid() || ok {
- t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok)
- }
-
- // len/cap
- cv = MakeChan(TypeOf(c), 10)
- c = cv.Interface().(chan int)
- for i := 0; i < 3; i++ {
- c <- i
- }
- if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {
- t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c))
- }
-}
-
-// caseInfo describes a single case in a select test.
-type caseInfo struct {
- desc string
- canSelect bool
- recv Value
- closed bool
- helper func()
- panic bool
-}
-
-var allselect = flag.Bool("allselect", false, "exhaustive select test")
-
-func TestSelect(t *testing.T) {
- selectWatch.once.Do(func() { go selectWatcher() })
-
- var x exhaustive
- nch := 0
- newop := func(n int, cap int) (ch, val Value) {
- nch++
- if nch%101%2 == 1 {
- c := make(chan int, cap)
- ch = ValueOf(c)
- val = ValueOf(n)
- } else {
- c := make(chan string, cap)
- ch = ValueOf(c)
- val = ValueOf(fmt.Sprint(n))
- }
- return
- }
-
- for n := 0; x.Next(); n++ {
- if testing.Short() && n >= 1000 {
- break
- }
- if n >= 100000 && !*allselect {
- break
- }
- if n%100000 == 0 && testing.Verbose() {
- println("TestSelect", n)
- }
- var cases []SelectCase
- var info []caseInfo
-
- // Ready send.
- if x.Maybe() {
- ch, val := newop(len(cases), 1)
- cases = append(cases, SelectCase{
- Dir: SelectSend,
- Chan: ch,
- Send: val,
- })
- info = append(info, caseInfo{desc: "ready send", canSelect: true})
- }
-
- // Ready recv.
- if x.Maybe() {
- ch, val := newop(len(cases), 1)
- ch.Send(val)
- cases = append(cases, SelectCase{
- Dir: SelectRecv,
- Chan: ch,
- })
- info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val})
- }
-
- // Blocking send.
- if x.Maybe() {
- ch, val := newop(len(cases), 0)
- cases = append(cases, SelectCase{
- Dir: SelectSend,
- Chan: ch,
- Send: val,
- })
- // Let it execute?
- if x.Maybe() {
- f := func() { ch.Recv() }
- info = append(info, caseInfo{desc: "blocking send", helper: f})
- } else {
- info = append(info, caseInfo{desc: "blocking send"})
- }
- }
-
- // Blocking recv.
- if x.Maybe() {
- ch, val := newop(len(cases), 0)
- cases = append(cases, SelectCase{
- Dir: SelectRecv,
- Chan: ch,
- })
- // Let it execute?
- if x.Maybe() {
- f := func() { ch.Send(val) }
- info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f})
- } else {
- info = append(info, caseInfo{desc: "blocking recv"})
- }
- }
-
- // Zero Chan send.
- if x.Maybe() {
- // Maybe include value to send.
- var val Value
- if x.Maybe() {
- val = ValueOf(100)
- }
- cases = append(cases, SelectCase{
- Dir: SelectSend,
- Send: val,
- })
- info = append(info, caseInfo{desc: "zero Chan send"})
- }
-
- // Zero Chan receive.
- if x.Maybe() {
- cases = append(cases, SelectCase{
- Dir: SelectRecv,
- })
- info = append(info, caseInfo{desc: "zero Chan recv"})
- }
-
- // nil Chan send.
- if x.Maybe() {
- cases = append(cases, SelectCase{
- Dir: SelectSend,
- Chan: ValueOf((chan int)(nil)),
- Send: ValueOf(101),
- })
- info = append(info, caseInfo{desc: "nil Chan send"})
- }
-
- // nil Chan recv.
- if x.Maybe() {
- cases = append(cases, SelectCase{
- Dir: SelectRecv,
- Chan: ValueOf((chan int)(nil)),
- })
- info = append(info, caseInfo{desc: "nil Chan recv"})
- }
-
- // closed Chan send.
- if x.Maybe() {
- ch := make(chan int)
- close(ch)
- cases = append(cases, SelectCase{
- Dir: SelectSend,
- Chan: ValueOf(ch),
- Send: ValueOf(101),
- })
- info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true})
- }
-
- // closed Chan recv.
- if x.Maybe() {
- ch, val := newop(len(cases), 0)
- ch.Close()
- val = Zero(val.Type())
- cases = append(cases, SelectCase{
- Dir: SelectRecv,
- Chan: ch,
- })
- info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val})
- }
-
- var helper func() // goroutine to help the select complete
-
- // Add default? Must be last case here, but will permute.
- // Add the default if the select would otherwise
- // block forever, and maybe add it anyway.
- numCanSelect := 0
- canProceed := false
- canBlock := true
- canPanic := false
- helpers := []int{}
- for i, c := range info {
- if c.canSelect {
- canProceed = true
- canBlock = false
- numCanSelect++
- if c.panic {
- canPanic = true
- }
- } else if c.helper != nil {
- canProceed = true
- helpers = append(helpers, i)
- }
- }
- if !canProceed || x.Maybe() {
- cases = append(cases, SelectCase{
- Dir: SelectDefault,
- })
- info = append(info, caseInfo{desc: "default", canSelect: canBlock})
- numCanSelect++
- } else if canBlock {
- // Select needs to communicate with another goroutine.
- cas := &info[helpers[x.Choose(len(helpers))]]
- helper = cas.helper
- cas.canSelect = true
- numCanSelect++
- }
-
- // Permute cases and case info.
- // Doing too much here makes the exhaustive loop
- // too exhausting, so just do two swaps.
- for loop := 0; loop < 2; loop++ {
- i := x.Choose(len(cases))
- j := x.Choose(len(cases))
- cases[i], cases[j] = cases[j], cases[i]
- info[i], info[j] = info[j], info[i]
- }
-
- if helper != nil {
- // We wait before kicking off a goroutine to satisfy a blocked select.
- // The pause needs to be big enough to let the select block before
- // we run the helper, but if we lose that race once in a while it's okay: the
- // select will just proceed immediately. Not a big deal.
- // For short tests we can grow [sic] the timeout a bit without fear of taking too long
- pause := 10 * time.Microsecond
- if testing.Short() {
- pause = 100 * time.Microsecond
- }
- time.AfterFunc(pause, helper)
- }
-
- // Run select.
- i, recv, recvOK, panicErr := runSelect(cases, info)
- if panicErr != nil && !canPanic {
- t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr)
- }
- if panicErr == nil && canPanic && numCanSelect == 1 {
- t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i)
- }
- if panicErr != nil {
- continue
- }
-
- cas := info[i]
- if !cas.canSelect {
- recvStr := ""
- if recv.IsValid() {
- recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK)
- }
- t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr)
- continue
- }
- if cas.panic {
- t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i)
- continue
- }
-
- if cases[i].Dir == SelectRecv {
- if !recv.IsValid() {
- t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)
- }
- if !cas.recv.IsValid() {
- t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i)
- }
- if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {
- if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {
- t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())
- }
- t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)
- }
- } else {
- if recv.IsValid() || recvOK {
- t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false)
- }
- }
- }
-}
-
-// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
-// If the selectWatcher notices that the select has been blocked for >1 second, it prints
-// an error describing the select and panics the entire test binary.
-var selectWatch struct {
- sync.Mutex
- once sync.Once
- now time.Time
- info []caseInfo
-}
-
-func selectWatcher() {
- for {
- time.Sleep(1 * time.Second)
- selectWatch.Lock()
- if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
- fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
- panic("select stuck")
- }
- selectWatch.Unlock()
- }
-}
-
-// runSelect runs a single select test.
-// It returns the values returned by Select but also returns
-// a panic value if the Select panics.
-func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) {
- defer func() {
- panicErr = recover()
-
- selectWatch.Lock()
- selectWatch.info = nil
- selectWatch.Unlock()
- }()
-
- selectWatch.Lock()
- selectWatch.now = time.Now()
- selectWatch.info = info
- selectWatch.Unlock()
-
- chosen, recv, recvOK = Select(cases)
- return
-}
-
-// fmtSelect formats the information about a single select test.
-func fmtSelect(info []caseInfo) string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "\nselect {\n")
- for i, cas := range info {
- fmt.Fprintf(&buf, "%d: %s", i, cas.desc)
- if cas.recv.IsValid() {
- fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface())
- }
- if cas.canSelect {
- fmt.Fprintf(&buf, " canselect")
- }
- if cas.panic {
- fmt.Fprintf(&buf, " panic")
- }
- fmt.Fprintf(&buf, "\n")
- }
- fmt.Fprintf(&buf, "}")
- return buf.String()
-}
-
-type two [2]uintptr
-
-// Difficult test for function call because of
-// implicit padding between arguments.
-func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {
- return b, c, d, e, f, g, h
-}
-
-func TestFunc(t *testing.T) {
- ret := ValueOf(dummy).Call([]Value{
- ValueOf(byte(10)),
- ValueOf(20),
- ValueOf(byte(30)),
- ValueOf(two{40, 50}),
- ValueOf(byte(60)),
- ValueOf(float32(70)),
- ValueOf(byte(80)),
- })
- if len(ret) != 7 {
- t.Fatalf("Call returned %d values, want 7", len(ret))
- }
-
- i := byte(ret[0].Uint())
- j := int(ret[1].Int())
- k := byte(ret[2].Uint())
- l := ret[3].Interface().(two)
- m := byte(ret[4].Uint())
- n := float32(ret[5].Float())
- o := byte(ret[6].Uint())
-
- if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
- t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
- }
-}
-
-type emptyStruct struct{}
-
-type nonEmptyStruct struct {
- member int
-}
-
-func returnEmpty() emptyStruct {
- return emptyStruct{}
-}
-
-func takesEmpty(e emptyStruct) {
-}
-
-func returnNonEmpty(i int) nonEmptyStruct {
- return nonEmptyStruct{member: i}
-}
-
-func takesNonEmpty(n nonEmptyStruct) int {
- return n.member
-}
-
-func TestCallWithStruct(t *testing.T) {
- r := ValueOf(returnEmpty).Call(nil)
- if len(r) != 1 || r[0].Type() != TypeOf(emptyStruct{}) {
- t.Errorf("returning empty struct returned %#v instead", r)
- }
- r = ValueOf(takesEmpty).Call([]Value{ValueOf(emptyStruct{})})
- if len(r) != 0 {
- t.Errorf("takesEmpty returned values: %#v", r)
- }
- r = ValueOf(returnNonEmpty).Call([]Value{ValueOf(42)})
- if len(r) != 1 || r[0].Type() != TypeOf(nonEmptyStruct{}) || r[0].Field(0).Int() != 42 {
- t.Errorf("returnNonEmpty returned %#v", r)
- }
- r = ValueOf(takesNonEmpty).Call([]Value{ValueOf(nonEmptyStruct{member: 42})})
- if len(r) != 1 || r[0].Type() != TypeOf(1) || r[0].Int() != 42 {
- t.Errorf("takesNonEmpty returned %#v", r)
- }
-}
-
-func TestMakeFunc(t *testing.T) {
- f := dummy
- fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
- ValueOf(&f).Elem().Set(fv)
-
- // Call g with small arguments so that there is
- // something predictable (and different from the
- // correct results) in those positions on the stack.
- g := dummy
- g(1, 2, 3, two{4, 5}, 6, 7, 8)
-
- // Call constructed function f.
- i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)
- if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
- t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
- }
-}
-
-func TestMakeFuncInterface(t *testing.T) {
- fn := func(i int) int { return i }
- incr := func(in []Value) []Value {
- return []Value{ValueOf(int(in[0].Int() + 1))}
- }
- fv := MakeFunc(TypeOf(fn), incr)
- ValueOf(&fn).Elem().Set(fv)
- if r := fn(2); r != 3 {
- t.Errorf("Call returned %d, want 3", r)
- }
- if r := fv.Call([]Value{ValueOf(14)})[0].Int(); r != 15 {
- t.Errorf("Call returned %d, want 15", r)
- }
- if r := fv.Interface().(func(int) int)(26); r != 27 {
- t.Errorf("Call returned %d, want 27", r)
- }
-}
-
-func TestMakeFuncVariadic(t *testing.T) {
- // Test that variadic arguments are packed into a slice and passed as last arg
- fn := func(_ int, is ...int) []int { return nil }
- fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })
- ValueOf(&fn).Elem().Set(fv)
-
- r := fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
- if r[0] != 2 || r[1] != 3 {
- t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
- }
-
- r = fv.CallSlice([]Value{ValueOf(1), ValueOf([]int{2, 3})})[0].Interface().([]int)
- if r[0] != 2 || r[1] != 3 {
- t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
- }
-}
-
-type Point struct {
- x, y int
-}
-
-// This will be index 0.
-func (p Point) AnotherMethod(scale int) int {
- return -1
-}
-
-// This will be index 1.
-func (p Point) Dist(scale int) int {
- //println("Point.Dist", p.x, p.y, scale)
- return p.x*p.x*scale + p.y*p.y*scale
-}
-
-func TestMethod(t *testing.T) {
- // Non-curried method of type.
- p := Point{3, 4}
- i := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Type Method returned %d; want 250", i)
- }
-
- m, ok := TypeOf(p).MethodByName("Dist")
- if !ok {
- t.Fatalf("method by name failed")
- }
- i = m.Func.Call([]Value{ValueOf(p), ValueOf(11)})[0].Int()
- if i != 275 {
- t.Errorf("Type MethodByName returned %d; want 275", i)
- }
-
- i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
- if i != 300 {
- t.Errorf("Pointer Type Method returned %d; want 300", i)
- }
-
- m, ok = TypeOf(&p).MethodByName("Dist")
- if !ok {
- t.Fatalf("ptr method by name failed")
- }
- i = m.Func.Call([]Value{ValueOf(&p), ValueOf(13)})[0].Int()
- if i != 325 {
- t.Errorf("Pointer Type MethodByName returned %d; want 325", i)
- }
-
- // Curried method of value.
- tfunc := TypeOf((func(int) int)(nil))
- v := ValueOf(p).Method(1)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(14)})[0].Int()
- if i != 350 {
- t.Errorf("Value Method returned %d; want 350", i)
- }
- v = ValueOf(p).MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(15)})[0].Int()
- if i != 375 {
- t.Errorf("Value MethodByName returned %d; want 375", i)
- }
-
- // Curried method of pointer.
- v = ValueOf(&p).Method(1)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(16)})[0].Int()
- if i != 400 {
- t.Errorf("Pointer Value Method returned %d; want 400", i)
- }
- v = ValueOf(&p).MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(17)})[0].Int()
- if i != 425 {
- t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
- }
-
- // Curried method of interface value.
- // Have to wrap interface value in a struct to get at it.
- // Passing it to ValueOf directly would
- // access the underlying Point, not the interface.
- var x interface {
- Dist(int) int
- } = p
- pv := ValueOf(&x).Elem()
- v = pv.Method(0)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(18)})[0].Int()
- if i != 450 {
- t.Errorf("Interface Method returned %d; want 450", i)
- }
- v = pv.MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = v.Call([]Value{ValueOf(19)})[0].Int()
- if i != 475 {
- t.Errorf("Interface MethodByName returned %d; want 475", i)
- }
-}
-
-func TestMethodValue(t *testing.T) {
- p := Point{3, 4}
- var i int64
-
- // Curried method of value.
- tfunc := TypeOf((func(int) int)(nil))
- v := ValueOf(p).Method(1)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Value Method returned %d; want 250", i)
- }
- v = ValueOf(p).MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(11)})[0].Int()
- if i != 275 {
- t.Errorf("Value MethodByName returned %d; want 275", i)
- }
-
- // Curried method of pointer.
- v = ValueOf(&p).Method(1)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(12)})[0].Int()
- if i != 300 {
- t.Errorf("Pointer Value Method returned %d; want 300", i)
- }
- v = ValueOf(&p).MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(13)})[0].Int()
- if i != 325 {
- t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
- }
-
- // Curried method of pointer to pointer.
- pp := &p
- v = ValueOf(&pp).Elem().Method(1)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Pointer Value Method Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
- if i != 350 {
- t.Errorf("Pointer Pointer Value Method returned %d; want 350", i)
- }
- v = ValueOf(&pp).Elem().MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Pointer Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
- if i != 375 {
- t.Errorf("Pointer Pointer Value MethodByName returned %d; want 375", i)
- }
-
- // Curried method of interface value.
- // Have to wrap interface value in a struct to get at it.
- // Passing it to ValueOf directly would
- // access the underlying Point, not the interface.
- var s = struct {
- X interface {
- Dist(int) int
- }
- }{p}
- pv := ValueOf(s).Field(0)
- v = pv.Method(0)
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(16)})[0].Int()
- if i != 400 {
- t.Errorf("Interface Method returned %d; want 400", i)
- }
- v = pv.MethodByName("Dist")
- if tt := v.Type(); tt != tfunc {
- t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
- }
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(17)})[0].Int()
- if i != 425 {
- t.Errorf("Interface MethodByName returned %d; want 425", i)
- }
-}
-
-// Reflect version of $GOROOT/test/method5.go
-
-// Concrete types implementing M method.
-// Smaller than a word, word-sized, larger than a word.
-// Value and pointer receivers.
-
-type Tinter interface {
- M(int, byte) (byte, int)
-}
-
-type Tsmallv byte
-
-func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x + int(v) }
-
-type Tsmallp byte
-
-func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
-
-type Twordv uintptr
-
-func (v Twordv) M(x int, b byte) (byte, int) { return b, x + int(v) }
-
-type Twordp uintptr
-
-func (p *Twordp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
-
-type Tbigv [2]uintptr
-
-func (v Tbigv) M(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
-
-type Tbigp [2]uintptr
-
-func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
-
-// Again, with an unexported method.
-
-type tsmallv byte
-
-func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) }
-
-type tsmallp byte
-
-func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
-
-type twordv uintptr
-
-func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) }
-
-type twordp uintptr
-
-func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
-
-type tbigv [2]uintptr
-
-func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
-
-type tbigp [2]uintptr
-
-func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
-
-type tinter interface {
- m(int, byte) (byte, int)
-}
-
-// Embedding via pointer.
-
-type Tm1 struct {
- Tm2
-}
-
-type Tm2 struct {
- *Tm3
-}
-
-type Tm3 struct {
- *Tm4
-}
-
-type Tm4 struct {
-}
-
-func (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 }
-
-func TestMethod5(t *testing.T) {
- CheckF := func(name string, f func(int, byte) (byte, int), inc int) {
- b, x := f(1000, 99)
- if b != 99 || x != 1000+inc {
- t.Errorf("%s(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
- }
- }
-
- CheckV := func(name string, i Value, inc int) {
- bx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))})
- b := bx[0].Interface()
- x := bx[1].Interface()
- if b != byte(99) || x != 1000+inc {
- t.Errorf("direct %s.M(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
- }
-
- CheckF(name+".M", i.Method(0).Interface().(func(int, byte) (byte, int)), inc)
- }
-
- var TinterType = TypeOf(new(Tinter)).Elem()
- var tinterType = TypeOf(new(tinter)).Elem()
-
- CheckI := func(name string, i interface{}, inc int) {
- v := ValueOf(i)
- CheckV(name, v, inc)
- CheckV("(i="+name+")", v.Convert(TinterType), inc)
- }
-
- sv := Tsmallv(1)
- CheckI("sv", sv, 1)
- CheckI("&sv", &sv, 1)
-
- sp := Tsmallp(2)
- CheckI("&sp", &sp, 2)
-
- wv := Twordv(3)
- CheckI("wv", wv, 3)
- CheckI("&wv", &wv, 3)
-
- wp := Twordp(4)
- CheckI("&wp", &wp, 4)
-
- bv := Tbigv([2]uintptr{5, 6})
- CheckI("bv", bv, 11)
- CheckI("&bv", &bv, 11)
-
- bp := Tbigp([2]uintptr{7, 8})
- CheckI("&bp", &bp, 15)
-
- t4 := Tm4{}
- t3 := Tm3{&t4}
- t2 := Tm2{&t3}
- t1 := Tm1{t2}
- CheckI("t4", t4, 40)
- CheckI("&t4", &t4, 40)
- CheckI("t3", t3, 40)
- CheckI("&t3", &t3, 40)
- CheckI("t2", t2, 40)
- CheckI("&t2", &t2, 40)
- CheckI("t1", t1, 40)
- CheckI("&t1", &t1, 40)
-
- methodShouldPanic := func(name string, i interface{}) {
- v := ValueOf(i)
- m := v.Method(0)
- shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
- shouldPanic(func() { m.Interface() })
-
- v = v.Convert(tinterType)
- m = v.Method(0)
- shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
- shouldPanic(func() { m.Interface() })
- }
-
- _sv := tsmallv(1)
- methodShouldPanic("_sv", _sv)
- methodShouldPanic("&_sv", &_sv)
-
- _sp := tsmallp(2)
- methodShouldPanic("&_sp", &_sp)
-
- _wv := twordv(3)
- methodShouldPanic("_wv", _wv)
- methodShouldPanic("&_wv", &_wv)
-
- _wp := twordp(4)
- methodShouldPanic("&_wp", &_wp)
-
- _bv := tbigv([2]uintptr{5, 6})
- methodShouldPanic("_bv", _bv)
- methodShouldPanic("&_bv", &_bv)
-
- _bp := tbigp([2]uintptr{7, 8})
- methodShouldPanic("&_bp", &_bp)
-
- var tnil Tinter
- vnil := ValueOf(&tnil).Elem()
- shouldPanic(func() { vnil.Method(0) })
-}
-
-func TestInterfaceSet(t *testing.T) {
- p := &Point{3, 4}
-
- var s struct {
- I interface{}
- P interface {
- Dist(int) int
- }
- }
- sv := ValueOf(&s).Elem()
- sv.Field(0).Set(ValueOf(p))
- if q := s.I.(*Point); q != p {
- t.Errorf("i: have %p want %p", q, p)
- }
-
- pv := sv.Field(1)
- pv.Set(ValueOf(p))
- if q := s.P.(*Point); q != p {
- t.Errorf("i: have %p want %p", q, p)
- }
-
- i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Interface Method returned %d; want 250", i)
- }
-}
-
-type T1 struct {
- a string
- int
-}
-
-func TestAnonymousFields(t *testing.T) {
- var field StructField
- var ok bool
- var t1 T1
- type1 := TypeOf(t1)
- if field, ok = type1.FieldByName("int"); !ok {
- t.Fatal("no field 'int'")
- }
- if field.Index[0] != 1 {
- t.Error("field index should be 1; is", field.Index)
- }
-}
-
-type FTest struct {
- s interface{}
- name string
- index []int
- value int
-}
-
-type D1 struct {
- d int
-}
-type D2 struct {
- d int
-}
-
-type S0 struct {
- A, B, C int
- D1
- D2
-}
-
-type S1 struct {
- B int
- S0
-}
-
-type S2 struct {
- A int
- *S1
-}
-
-type S1x struct {
- S1
-}
-
-type S1y struct {
- S1
-}
-
-type S3 struct {
- S1x
- S2
- D, E int
- *S1y
-}
-
-type S4 struct {
- *S4
- A int
-}
-
-// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
-type S5 struct {
- S6
- S7
- S8
-}
-
-type S6 struct {
- X int
-}
-
-type S7 S6
-
-type S8 struct {
- S9
-}
-
-type S9 struct {
- X int
- Y int
-}
-
-// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
-type S10 struct {
- S11
- S12
- S13
-}
-
-type S11 struct {
- S6
-}
-
-type S12 struct {
- S6
-}
-
-type S13 struct {
- S8
-}
-
-// The X in S15.S11.S1 and S16.S11.S1 annihilate.
-type S14 struct {
- S15
- S16
-}
-
-type S15 struct {
- S11
-}
-
-type S16 struct {
- S11
-}
-
-var fieldTests = []FTest{
- {struct{}{}, "", nil, 0},
- {struct{}{}, "Foo", nil, 0},
- {S0{A: 'a'}, "A", []int{0}, 'a'},
- {S0{}, "D", nil, 0},
- {S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
- {S1{B: 'b'}, "B", []int{0}, 'b'},
- {S1{}, "S0", []int{1}, 0},
- {S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
- {S2{A: 'a'}, "A", []int{0}, 'a'},
- {S2{}, "S1", []int{1}, 0},
- {S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
- {S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
- {S2{}, "D", nil, 0},
- {S3{}, "S1", nil, 0},
- {S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
- {S3{}, "B", nil, 0},
- {S3{D: 'd'}, "D", []int{2}, 0},
- {S3{E: 'e'}, "E", []int{3}, 'e'},
- {S4{A: 'a'}, "A", []int{1}, 'a'},
- {S4{}, "B", nil, 0},
- {S5{}, "X", nil, 0},
- {S5{}, "Y", []int{2, 0, 1}, 0},
- {S10{}, "X", nil, 0},
- {S10{}, "Y", []int{2, 0, 0, 1}, 0},
- {S14{}, "X", nil, 0},
-}
-
-func TestFieldByIndex(t *testing.T) {
- for _, test := range fieldTests {
- s := TypeOf(test.s)
- f := s.FieldByIndex(test.index)
- if f.Name != "" {
- if test.index != nil {
- if f.Name != test.name {
- t.Errorf("%s.%s found; want %s", s.Name(), f.Name, test.name)
- }
- } else {
- t.Errorf("%s.%s found", s.Name(), f.Name)
- }
- } else if len(test.index) > 0 {
- t.Errorf("%s.%s not found", s.Name(), test.name)
- }
-
- if test.value != 0 {
- v := ValueOf(test.s).FieldByIndex(test.index)
- if v.IsValid() {
- if x, ok := v.Interface().(int); ok {
- if x != test.value {
- t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value)
- }
- } else {
- t.Errorf("%s%v value not an int", s.Name(), test.index)
- }
- } else {
- t.Errorf("%s%v value not found", s.Name(), test.index)
- }
- }
- }
-}
-
-func TestFieldByName(t *testing.T) {
- for _, test := range fieldTests {
- s := TypeOf(test.s)
- f, found := s.FieldByName(test.name)
- if found {
- if test.index != nil {
- // Verify field depth and index.
- if len(f.Index) != len(test.index) {
- t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)
- } else {
- for i, x := range f.Index {
- if x != test.index[i] {
- t.Errorf("%s.%s.Index[%d] is %d; want %d", s.Name(), test.name, i, x, test.index[i])
- }
- }
- }
- } else {
- t.Errorf("%s.%s found", s.Name(), f.Name)
- }
- } else if len(test.index) > 0 {
- t.Errorf("%s.%s not found", s.Name(), test.name)
- }
-
- if test.value != 0 {
- v := ValueOf(test.s).FieldByName(test.name)
- if v.IsValid() {
- if x, ok := v.Interface().(int); ok {
- if x != test.value {
- t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value)
- }
- } else {
- t.Errorf("%s.%s value not an int", s.Name(), test.name)
- }
- } else {
- t.Errorf("%s.%s value not found", s.Name(), test.name)
- }
- }
- }
-}
-
-func TestImportPath(t *testing.T) {
- tests := []struct {
- t Type
- path string
- }{
- {TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
- {TypeOf(int(0)), ""},
- {TypeOf(int8(0)), ""},
- {TypeOf(int16(0)), ""},
- {TypeOf(int32(0)), ""},
- {TypeOf(int64(0)), ""},
- {TypeOf(uint(0)), ""},
- {TypeOf(uint8(0)), ""},
- {TypeOf(uint16(0)), ""},
- {TypeOf(uint32(0)), ""},
- {TypeOf(uint64(0)), ""},
- {TypeOf(uintptr(0)), ""},
- {TypeOf(float32(0)), ""},
- {TypeOf(float64(0)), ""},
- {TypeOf(complex64(0)), ""},
- {TypeOf(complex128(0)), ""},
- {TypeOf(byte(0)), ""},
- {TypeOf(rune(0)), ""},
- {TypeOf([]byte(nil)), ""},
- {TypeOf([]rune(nil)), ""},
- {TypeOf(string("")), ""},
- {TypeOf((*interface{})(nil)).Elem(), ""},
- {TypeOf((*byte)(nil)), ""},
- {TypeOf((*rune)(nil)), ""},
- {TypeOf((*int64)(nil)), ""},
- {TypeOf(map[string]int{}), ""},
- {TypeOf((*error)(nil)).Elem(), ""},
- }
- for _, test := range tests {
- if path := test.t.PkgPath(); path != test.path {
- t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path)
- }
- }
-}
-
-func TestVariadicType(t *testing.T) {
- // Test example from Type documentation.
- var f func(x int, y ...float64)
- typ := TypeOf(f)
- if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) {
- sl := typ.In(1)
- if sl.Kind() == Slice {
- if sl.Elem() == TypeOf(0.0) {
- // ok
- return
- }
- }
- }
-
- // Failed
- t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64")
- s := fmt.Sprintf("have NumIn() = %d", typ.NumIn())
- for i := 0; i < typ.NumIn(); i++ {
- s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i))
- }
- t.Error(s)
-}
-
-type inner struct {
- x int
-}
-
-type outer struct {
- y int
- inner
-}
-
-func (*inner) m() {}
-func (*outer) m() {}
-
-func TestNestedMethods(t *testing.T) {
- typ := TypeOf((*outer)(nil))
- if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
- t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
- for i := 0; i < typ.NumMethod(); i++ {
- m := typ.Method(i)
- t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
- }
- }
-}
-
-type InnerInt struct {
- X int
-}
-
-type OuterInt struct {
- Y int
- InnerInt
-}
-
-func (i *InnerInt) M() int {
- return i.X
-}
-
-func TestEmbeddedMethods(t *testing.T) {
- typ := TypeOf((*OuterInt)(nil))
- if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
- t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
- for i := 0; i < typ.NumMethod(); i++ {
- m := typ.Method(i)
- t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
- }
- }
-
- i := &InnerInt{3}
- if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
- t.Errorf("i.M() = %d, want 3", v)
- }
-
- o := &OuterInt{1, InnerInt{2}}
- if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {
- t.Errorf("i.M() = %d, want 2", v)
- }
-
- f := (*OuterInt).M
- if v := f(o); v != 2 {
- t.Errorf("f(o) = %d, want 2", v)
- }
-}
-
-func TestPtrTo(t *testing.T) {
- var i int
-
- typ := TypeOf(i)
- for i = 0; i < 100; i++ {
- typ = PtrTo(typ)
- }
- for i = 0; i < 100; i++ {
- typ = typ.Elem()
- }
- if typ != TypeOf(i) {
- t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
- }
-}
-
-func TestPtrToGC(t *testing.T) {
- type T *uintptr
- tt := TypeOf(T(nil))
- pt := PtrTo(tt)
- const n = 100
- var x []interface{}
- for i := 0; i < n; i++ {
- v := New(pt)
- p := new(*uintptr)
- *p = new(uintptr)
- **p = uintptr(i)
- v.Elem().Set(ValueOf(p).Convert(pt))
- x = append(x, v.Interface())
- }
- runtime.GC()
-
- for i, xi := range x {
- k := ValueOf(xi).Elem().Elem().Elem().Interface().(uintptr)
- if k != uintptr(i) {
- t.Errorf("lost x[%d] = %d, want %d", i, k, i)
- }
- }
-}
-
-func TestAddr(t *testing.T) {
- var p struct {
- X, Y int
- }
-
- v := ValueOf(&p)
- v = v.Elem()
- v = v.Addr()
- v = v.Elem()
- v = v.Field(0)
- v.SetInt(2)
- if p.X != 2 {
- t.Errorf("Addr.Elem.Set failed to set value")
- }
-
- // Again but take address of the ValueOf value.
- // Exercises generation of PtrTypes not present in the binary.
- q := &p
- v = ValueOf(&q).Elem()
- v = v.Addr()
- v = v.Elem()
- v = v.Elem()
- v = v.Addr()
- v = v.Elem()
- v = v.Field(0)
- v.SetInt(3)
- if p.X != 3 {
- t.Errorf("Addr.Elem.Set failed to set value")
- }
-
- // Starting without pointer we should get changed value
- // in interface.
- qq := p
- v = ValueOf(&qq).Elem()
- v0 := v
- v = v.Addr()
- v = v.Elem()
- v = v.Field(0)
- v.SetInt(4)
- if p.X != 3 { // should be unchanged from last time
- t.Errorf("somehow value Set changed original p")
- }
- p = v0.Interface().(struct {
- X, Y int
- })
- if p.X != 4 {
- t.Errorf("Addr.Elem.Set valued to set value in top value")
- }
-
- // Verify that taking the address of a type gives us a pointer
- // which we can convert back using the usual interface
- // notation.
- var s struct {
- B *bool
- }
- ps := ValueOf(&s).Elem().Field(0).Addr().Interface()
- *(ps.(**bool)) = new(bool)
- if s.B == nil {
- t.Errorf("Addr.Interface direct assignment failed")
- }
-}
-
-func noAlloc(t *testing.T, n int, f func(int)) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- if runtime.GOMAXPROCS(0) > 1 {
- t.Skip("skipping; GOMAXPROCS>1")
- }
- i := -1
- allocs := testing.AllocsPerRun(n, func() {
- f(i)
- i++
- })
- if allocs > 0 {
- t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs)
- }
-}
-
-func TestAllocations(t *testing.T) {
- noAlloc(t, 100, func(j int) {
- var i interface{}
- var v Value
- i = 42 + j
- v = ValueOf(i)
- if int(v.Int()) != 42+j {
- panic("wrong int")
- }
- })
-}
-
-func TestSmallNegativeInt(t *testing.T) {
- i := int16(-1)
- v := ValueOf(i)
- if v.Int() != -1 {
- t.Errorf("int16(-1).Int() returned %v", v.Int())
- }
-}
-
-func TestIndex(t *testing.T) {
- xs := []byte{1, 2, 3, 4, 5, 6, 7, 8}
- v := ValueOf(xs).Index(3).Interface().(byte)
- if v != xs[3] {
- t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3])
- }
- xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}
- v = ValueOf(xa).Index(2).Interface().(byte)
- if v != xa[2] {
- t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2])
- }
- s := "0123456789"
- v = ValueOf(s).Index(3).Interface().(byte)
- if v != s[3] {
- t.Errorf("s.Index(3) = %v; expected %v", v, s[3])
- }
-}
-
-func TestSlice(t *testing.T) {
- xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
- v := ValueOf(xs).Slice(3, 5).Interface().([]int)
- if len(v) != 2 {
- t.Errorf("len(xs.Slice(3, 5)) = %d", len(v))
- }
- if cap(v) != 5 {
- t.Errorf("cap(xs.Slice(3, 5)) = %d", cap(v))
- }
- if !DeepEqual(v[0:5], xs[3:]) {
- t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
- }
- xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
- v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
- if len(v) != 3 {
- t.Errorf("len(xa.Slice(2, 5)) = %d", len(v))
- }
- if cap(v) != 6 {
- t.Errorf("cap(xa.Slice(2, 5)) = %d", cap(v))
- }
- if !DeepEqual(v[0:6], xa[2:]) {
- t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
- }
- s := "0123456789"
- vs := ValueOf(s).Slice(3, 5).Interface().(string)
- if vs != s[3:5] {
- t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
- }
-}
-
-func TestSlice3(t *testing.T) {
- xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
- v := ValueOf(xs).Slice3(3, 5, 7).Interface().([]int)
- if len(v) != 2 {
- t.Errorf("len(xs.Slice3(3, 5, 7)) = %d", len(v))
- }
- if cap(v) != 4 {
- t.Errorf("cap(xs.Slice3(3, 5, 7)) = %d", cap(v))
- }
- if !DeepEqual(v[0:4], xs[3:7:7]) {
- t.Errorf("xs.Slice3(3, 5, 7)[0:4] = %v", v[0:4])
- }
- rv := ValueOf(&xs).Elem()
- shouldPanic(func() { rv.Slice3(1, 2, 1) })
- shouldPanic(func() { rv.Slice3(1, 1, 11) })
- shouldPanic(func() { rv.Slice3(2, 2, 1) })
-
- xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
- v = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)
- if len(v) != 3 {
- t.Errorf("len(xa.Slice(2, 5, 6)) = %d", len(v))
- }
- if cap(v) != 4 {
- t.Errorf("cap(xa.Slice(2, 5, 6)) = %d", cap(v))
- }
- if !DeepEqual(v[0:4], xa[2:6:6]) {
- t.Errorf("xs.Slice(2, 5, 6)[0:4] = %v", v[0:4])
- }
- rv = ValueOf(&xa).Elem()
- shouldPanic(func() { rv.Slice3(1, 2, 1) })
- shouldPanic(func() { rv.Slice3(1, 1, 11) })
- shouldPanic(func() { rv.Slice3(2, 2, 1) })
-
- s := "hello world"
- rv = ValueOf(&s).Elem()
- shouldPanic(func() { rv.Slice3(1, 2, 3) })
-}
-
-func TestSetLenCap(t *testing.T) {
- xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
- xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
-
- vs := ValueOf(&xs).Elem()
- shouldPanic(func() { vs.SetLen(10) })
- shouldPanic(func() { vs.SetCap(10) })
- shouldPanic(func() { vs.SetLen(-1) })
- shouldPanic(func() { vs.SetCap(-1) })
- shouldPanic(func() { vs.SetCap(6) }) // smaller than len
- vs.SetLen(5)
- if len(xs) != 5 || cap(xs) != 8 {
- t.Errorf("after SetLen(5), len, cap = %d, %d, want 5, 8", len(xs), cap(xs))
- }
- vs.SetCap(6)
- if len(xs) != 5 || cap(xs) != 6 {
- t.Errorf("after SetCap(6), len, cap = %d, %d, want 5, 6", len(xs), cap(xs))
- }
- vs.SetCap(5)
- if len(xs) != 5 || cap(xs) != 5 {
- t.Errorf("after SetCap(5), len, cap = %d, %d, want 5, 5", len(xs), cap(xs))
- }
- shouldPanic(func() { vs.SetCap(4) }) // smaller than len
- shouldPanic(func() { vs.SetLen(6) }) // bigger than cap
-
- va := ValueOf(&xa).Elem()
- shouldPanic(func() { va.SetLen(8) })
- shouldPanic(func() { va.SetCap(8) })
-}
-
-func TestVariadic(t *testing.T) {
- var b bytes.Buffer
- V := ValueOf
-
- b.Reset()
- V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)})
- if b.String() != "hello, 42 world" {
- t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world")
- }
-
- b.Reset()
- V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})})
- if b.String() != "hello, 42 world" {
- t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world")
- }
-}
-
-func TestFuncArg(t *testing.T) {
- f1 := func(i int, f func(int) int) int { return f(i) }
- f2 := func(i int) int { return i + 1 }
- r := ValueOf(f1).Call([]Value{ValueOf(100), ValueOf(f2)})
- if r[0].Int() != 101 {
- t.Errorf("function returned %d, want 101", r[0].Int())
- }
-}
-
-var tagGetTests = []struct {
- Tag StructTag
- Key string
- Value string
-}{
- {`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`},
- {`protobuf:"PB(1,2)"`, `foo`, ``},
- {`protobuf:"PB(1,2)"`, `rotobuf`, ``},
- {`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
- {`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
-}
-
-func TestTagGet(t *testing.T) {
- for _, tt := range tagGetTests {
- if v := tt.Tag.Get(tt.Key); v != tt.Value {
- t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value)
- }
- }
-}
-
-func TestBytes(t *testing.T) {
- type B []byte
- x := B{1, 2, 3, 4}
- y := ValueOf(x).Bytes()
- if !bytes.Equal(x, y) {
- t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
- }
- if &x[0] != &y[0] {
- t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
- }
-}
-
-func TestSetBytes(t *testing.T) {
- type B []byte
- var x B
- y := []byte{1, 2, 3, 4}
- ValueOf(&x).Elem().SetBytes(y)
- if !bytes.Equal(x, y) {
- t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
- }
- if &x[0] != &y[0] {
- t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
- }
-}
-
-type Private struct {
- x int
- y **int
-}
-
-func (p *Private) m() {
-}
-
-type Public struct {
- X int
- Y **int
-}
-
-func (p *Public) M() {
-}
-
-func TestUnexported(t *testing.T) {
- var pub Public
- v := ValueOf(&pub)
- isValid(v.Elem().Field(0))
- isValid(v.Elem().Field(1))
- isValid(v.Elem().FieldByName("X"))
- isValid(v.Elem().FieldByName("Y"))
- isValid(v.Type().Method(0).Func)
- isNonNil(v.Elem().Field(0).Interface())
- isNonNil(v.Elem().Field(1).Interface())
- isNonNil(v.Elem().FieldByName("X").Interface())
- isNonNil(v.Elem().FieldByName("Y").Interface())
- isNonNil(v.Type().Method(0).Func.Interface())
-
- var priv Private
- v = ValueOf(&priv)
- isValid(v.Elem().Field(0))
- isValid(v.Elem().Field(1))
- isValid(v.Elem().FieldByName("x"))
- isValid(v.Elem().FieldByName("y"))
- isValid(v.Type().Method(0).Func)
- shouldPanic(func() { v.Elem().Field(0).Interface() })
- shouldPanic(func() { v.Elem().Field(1).Interface() })
- shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
- shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
- shouldPanic(func() { v.Type().Method(0).Func.Interface() })
-}
-
-func shouldPanic(f func()) {
- defer func() {
- if recover() == nil {
- panic("did not panic")
- }
- }()
- f()
-}
-
-func isNonNil(x interface{}) {
- if x == nil {
- panic("nil interface")
- }
-}
-
-func isValid(v Value) {
- if !v.IsValid() {
- panic("zero Value")
- }
-}
-
-func TestAlias(t *testing.T) {
- x := string("hello")
- v := ValueOf(&x).Elem()
- oldvalue := v.Interface()
- v.SetString("world")
- newvalue := v.Interface()
-
- if oldvalue != "hello" || newvalue != "world" {
- t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
- }
-}
-
-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
-
- // vout1 represents the in value converted to the in type.
- 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(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t1, out1, tt.in.Interface())
- }
-
- // vout2 represents the in value converted to the out type.
- vout2 := v1.Convert(t2)
- out2 := vout2.Interface()
- if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
- t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface())
- }
-
- // vout3 represents a new value of the out type, set to vout2. This makes
- // sure the converted value vout2 is really usable as a regular value.
- vout3 := New(t2).Elem()
- vout3.Set(vout2)
- out3 := vout3.Interface()
- if vout3.Type() != tt.out.Type() || !DeepEqual(out3, tt.out.Interface()) {
- t.Errorf("Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out3, 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(vout2) {
- t.Errorf("conversion output %v is RO, should not be", vout2)
- }
- if IsRO(vout3) {
- t.Errorf("set(conversion output) %v is RO, should not be", vout3)
- }
- 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)
- }
- }
- }
-}
-
-func TestOverflow(t *testing.T) {
- if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
- t.Errorf("%v wrongly overflows float64", 1e300)
- }
-
- maxFloat32 := float64((1<<24 - 1) << (127 - 23))
- if ovf := V(float32(0)).OverflowFloat(maxFloat32); ovf {
- t.Errorf("%v wrongly overflows float32", maxFloat32)
- }
- ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
- if ovf := V(float32(0)).OverflowFloat(ovfFloat32); !ovf {
- t.Errorf("%v should overflow float32", ovfFloat32)
- }
- if ovf := V(float32(0)).OverflowFloat(-ovfFloat32); !ovf {
- t.Errorf("%v should overflow float32", -ovfFloat32)
- }
-
- maxInt32 := int64(0x7fffffff)
- if ovf := V(int32(0)).OverflowInt(maxInt32); ovf {
- t.Errorf("%v wrongly overflows int32", maxInt32)
- }
- if ovf := V(int32(0)).OverflowInt(-1 << 31); ovf {
- t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
- }
- ovfInt32 := int64(1 << 31)
- if ovf := V(int32(0)).OverflowInt(ovfInt32); !ovf {
- t.Errorf("%v should overflow int32", ovfInt32)
- }
-
- maxUint32 := uint64(0xffffffff)
- if ovf := V(uint32(0)).OverflowUint(maxUint32); ovf {
- t.Errorf("%v wrongly overflows uint32", maxUint32)
- }
- ovfUint32 := uint64(1 << 32)
- if ovf := V(uint32(0)).OverflowUint(ovfUint32); !ovf {
- t.Errorf("%v should overflow uint32", ovfUint32)
- }
-}
-
-func checkSameType(t *testing.T, x, y interface{}) {
- if TypeOf(x) != TypeOf(y) {
- t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
- }
-}
-
-func TestArrayOf(t *testing.T) {
- // check construction and use of type not in binary
- type T int
- at := ArrayOf(10, TypeOf(T(1)))
- v := New(at).Elem()
- for i := 0; i < v.Len(); i++ {
- v.Index(i).Set(ValueOf(T(i)))
- }
- s := fmt.Sprint(v.Interface())
- want := "[0 1 2 3 4 5 6 7 8 9]"
- if s != want {
- t.Errorf("constructed array = %s, want %s", s, want)
- }
-
- // check that type already in binary is found
- checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
-}
-
-func TestSliceOf(t *testing.T) {
- // check construction and use of type not in binary
- type T int
- st := SliceOf(TypeOf(T(1)))
- v := MakeSlice(st, 10, 10)
- runtime.GC()
- for i := 0; i < v.Len(); i++ {
- v.Index(i).Set(ValueOf(T(i)))
- runtime.GC()
- }
- s := fmt.Sprint(v.Interface())
- want := "[0 1 2 3 4 5 6 7 8 9]"
- if s != want {
- t.Errorf("constructed slice = %s, want %s", s, want)
- }
-
- // check that type already in binary is found
- type T1 int
- checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
-}
-
-func TestSliceOverflow(t *testing.T) {
- // check that MakeSlice panics when size of slice overflows uint
- const S = 1e6
- s := uint(S)
- l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1
- if l*s >= s {
- t.Fatal("slice size does not overflow")
- }
- var x [S]byte
- st := SliceOf(TypeOf(x))
- defer func() {
- err := recover()
- if err == nil {
- t.Fatal("slice overflow does not panic")
- }
- }()
- MakeSlice(st, int(l), int(l))
-}
-
-func TestSliceOfGC(t *testing.T) {
- type T *uintptr
- tt := TypeOf(T(nil))
- st := SliceOf(tt)
- const n = 100
- var x []interface{}
- for i := 0; i < n; i++ {
- v := MakeSlice(st, n, n)
- for j := 0; j < v.Len(); j++ {
- p := new(uintptr)
- *p = uintptr(i*n + j)
- v.Index(j).Set(ValueOf(p).Convert(tt))
- }
- x = append(x, v.Interface())
- }
- runtime.GC()
-
- for i, xi := range x {
- v := ValueOf(xi)
- for j := 0; j < v.Len(); j++ {
- k := v.Index(j).Elem().Interface()
- if k != uintptr(i*n+j) {
- t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
- }
- }
- }
-}
-
-func TestChanOf(t *testing.T) {
- // check construction and use of type not in binary
- type T string
- ct := ChanOf(BothDir, TypeOf(T("")))
- v := MakeChan(ct, 2)
- runtime.GC()
- v.Send(ValueOf(T("hello")))
- runtime.GC()
- v.Send(ValueOf(T("world")))
- runtime.GC()
-
- sv1, _ := v.Recv()
- sv2, _ := v.Recv()
- s1 := sv1.String()
- s2 := sv2.String()
- if s1 != "hello" || s2 != "world" {
- t.Errorf("constructed chan: have %q, %q, want %q, %q", s1, s2, "hello", "world")
- }
-
- // check that type already in binary is found
- type T1 int
- checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
-}
-
-func TestChanOfGC(t *testing.T) {
- done := make(chan bool, 1)
- go func() {
- select {
- case <-done:
- case <-time.After(5 * time.Second):
- panic("deadlock in TestChanOfGC")
- }
- }()
-
- defer func() {
- done <- true
- }()
-
- type T *uintptr
- tt := TypeOf(T(nil))
- ct := ChanOf(BothDir, tt)
-
- // NOTE: The garbage collector handles allocated channels specially,
- // so we have to save pointers to channels in x; the pointer code will
- // use the gc info in the newly constructed chan type.
- const n = 100
- var x []interface{}
- for i := 0; i < n; i++ {
- v := MakeChan(ct, n)
- for j := 0; j < n; j++ {
- p := new(uintptr)
- *p = uintptr(i*n + j)
- v.Send(ValueOf(p).Convert(tt))
- }
- pv := New(ct)
- pv.Elem().Set(v)
- x = append(x, pv.Interface())
- }
- runtime.GC()
-
- for i, xi := range x {
- v := ValueOf(xi).Elem()
- for j := 0; j < n; j++ {
- pv, _ := v.Recv()
- k := pv.Elem().Interface()
- if k != uintptr(i*n+j) {
- t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
- }
- }
- }
-}
-
-func TestMapOf(t *testing.T) {
- // check construction and use of type not in binary
- type K string
- type V float64
-
- v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
- runtime.GC()
- v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
- runtime.GC()
-
- s := fmt.Sprint(v.Interface())
- want := "map[a:1]"
- if s != want {
- t.Errorf("constructed map = %s, want %s", s, want)
- }
-
- // check that type already in binary is found
- checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
-
- // check that invalid key type panics
- shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
-}
-
-func TestMapOfGCKeys(t *testing.T) {
- type T *uintptr
- tt := TypeOf(T(nil))
- mt := MapOf(tt, TypeOf(false))
-
- // NOTE: The garbage collector handles allocated maps specially,
- // so we have to save pointers to maps in x; the pointer code will
- // use the gc info in the newly constructed map type.
- const n = 100
- var x []interface{}
- for i := 0; i < n; i++ {
- v := MakeMap(mt)
- for j := 0; j < n; j++ {
- p := new(uintptr)
- *p = uintptr(i*n + j)
- v.SetMapIndex(ValueOf(p).Convert(tt), ValueOf(true))
- }
- pv := New(mt)
- pv.Elem().Set(v)
- x = append(x, pv.Interface())
- }
- runtime.GC()
-
- for i, xi := range x {
- v := ValueOf(xi).Elem()
- var out []int
- for _, kv := range v.MapKeys() {
- out = append(out, int(kv.Elem().Interface().(uintptr)))
- }
- sort.Ints(out)
- for j, k := range out {
- if k != i*n+j {
- t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
- }
- }
- }
-}
-
-func TestMapOfGCValues(t *testing.T) {
- type T *uintptr
- tt := TypeOf(T(nil))
- mt := MapOf(TypeOf(1), tt)
-
- // NOTE: The garbage collector handles allocated maps specially,
- // so we have to save pointers to maps in x; the pointer code will
- // use the gc info in the newly constructed map type.
- const n = 100
- var x []interface{}
- for i := 0; i < n; i++ {
- v := MakeMap(mt)
- for j := 0; j < n; j++ {
- p := new(uintptr)
- *p = uintptr(i*n + j)
- v.SetMapIndex(ValueOf(j), ValueOf(p).Convert(tt))
- }
- pv := New(mt)
- pv.Elem().Set(v)
- x = append(x, pv.Interface())
- }
- runtime.GC()
-
- for i, xi := range x {
- v := ValueOf(xi).Elem()
- for j := 0; j < n; j++ {
- k := v.MapIndex(ValueOf(j)).Elem().Interface().(uintptr)
- if k != uintptr(i*n+j) {
- t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
- }
- }
- }
-}
-
-type B1 struct {
- X int
- Y int
- Z int
-}
-
-func BenchmarkFieldByName1(b *testing.B) {
- t := TypeOf(B1{})
- for i := 0; i < b.N; i++ {
- t.FieldByName("Z")
- }
-}
-
-func BenchmarkFieldByName2(b *testing.B) {
- t := TypeOf(S3{})
- for i := 0; i < b.N; i++ {
- t.FieldByName("B")
- }
-}
-
-type R0 struct {
- *R1
- *R2
- *R3
- *R4
-}
-
-type R1 struct {
- *R5
- *R6
- *R7
- *R8
-}
-
-type R2 R1
-type R3 R1
-type R4 R1
-
-type R5 struct {
- *R9
- *R10
- *R11
- *R12
-}
-
-type R6 R5
-type R7 R5
-type R8 R5
-
-type R9 struct {
- *R13
- *R14
- *R15
- *R16
-}
-
-type R10 R9
-type R11 R9
-type R12 R9
-
-type R13 struct {
- *R17
- *R18
- *R19
- *R20
-}
-
-type R14 R13
-type R15 R13
-type R16 R13
-
-type R17 struct {
- *R21
- *R22
- *R23
- *R24
-}
-
-type R18 R17
-type R19 R17
-type R20 R17
-
-type R21 struct {
- X int
-}
-
-type R22 R21
-type R23 R21
-type R24 R21
-
-func TestEmbed(t *testing.T) {
- typ := TypeOf(R0{})
- f, ok := typ.FieldByName("X")
- if ok {
- t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index)
- }
-}
-
-func BenchmarkFieldByName3(b *testing.B) {
- t := TypeOf(R0{})
- for i := 0; i < b.N; i++ {
- t.FieldByName("X")
- }
-}
-
-type S struct {
- i1 int64
- i2 int64
-}
-
-func BenchmarkInterfaceBig(b *testing.B) {
- v := ValueOf(S{})
- for i := 0; i < b.N; i++ {
- v.Interface()
- }
- b.StopTimer()
-}
-
-func TestAllocsInterfaceBig(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- v := ValueOf(S{})
- if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
- t.Error("allocs:", allocs)
- }
-}
-
-func BenchmarkInterfaceSmall(b *testing.B) {
- v := ValueOf(int64(0))
- for i := 0; i < b.N; i++ {
- v.Interface()
- }
-}
-
-func TestAllocsInterfaceSmall(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- v := ValueOf(int64(0))
- if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
- t.Error("allocs:", allocs)
- }
-}
-
-// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
-// The basic usage is:
-//
-// for x.Next() {
-// ... code using x.Maybe() or x.Choice(n) to create test cases ...
-// }
-//
-// Each iteration of the loop returns a different set of results, until all
-// possible result sets have been explored. It is okay for different code paths
-// to make different method call sequences on x, but there must be no
-// other source of non-determinism in the call sequences.
-//
-// When faced with a new decision, x chooses randomly. Future explorations
-// of that path will choose successive values for the result. Thus, stopping
-// the loop after a fixed number of iterations gives somewhat stochastic
-// testing.
-//
-// Example:
-//
-// for x.Next() {
-// v := make([]bool, x.Choose(4))
-// for i := range v {
-// v[i] = x.Maybe()
-// }
-// fmt.Println(v)
-// }
-//
-// prints (in some order):
-//
-// []
-// [false]
-// [true]
-// [false false]
-// [false true]
-// ...
-// [true true]
-// [false false false]
-// ...
-// [true true true]
-// [false false false false]
-// ...
-// [true true true true]
-//
-type exhaustive struct {
- r *rand.Rand
- pos int
- last []choice
-}
-
-type choice struct {
- off int
- n int
- max int
-}
-
-func (x *exhaustive) Next() bool {
- if x.r == nil {
- x.r = rand.New(rand.NewSource(time.Now().UnixNano()))
- }
- x.pos = 0
- if x.last == nil {
- x.last = []choice{}
- return true
- }
- for i := len(x.last) - 1; i >= 0; i-- {
- c := &x.last[i]
- if c.n+1 < c.max {
- c.n++
- x.last = x.last[:i+1]
- return true
- }
- }
- return false
-}
-
-func (x *exhaustive) Choose(max int) int {
- if x.pos >= len(x.last) {
- x.last = append(x.last, choice{x.r.Intn(max), 0, max})
- }
- c := &x.last[x.pos]
- x.pos++
- if c.max != max {
- panic("inconsistent use of exhaustive tester")
- }
- return (c.n + c.off) % max
-}
-
-func (x *exhaustive) Maybe() bool {
- return x.Choose(2) == 1
-}
-
-func GCFunc(args []Value) []Value {
- runtime.GC()
- return []Value{}
-}
-
-func TestReflectFuncTraceback(t *testing.T) {
- f := MakeFunc(TypeOf(func() {}), GCFunc)
- f.Call([]Value{})
-}
-
-func (p Point) GCMethod(k int) int {
- runtime.GC()
- return k + p.x
-}
-
-func TestReflectMethodTraceback(t *testing.T) {
- p := Point{3, 4}
- m := ValueOf(p).MethodByName("GCMethod")
- i := ValueOf(m.Interface()).Call([]Value{ValueOf(5)})[0].Int()
- if i != 8 {
- t.Errorf("Call returned %d; want 8", i)
- }
-}
-
-func TestBigZero(t *testing.T) {
- const size = 1 << 10
- var v [size]byte
- z := Zero(ValueOf(v).Type()).Interface().([size]byte)
- for i := 0; i < size; i++ {
- if z[i] != 0 {
- t.Fatalf("Zero object not all zero, index %d", i)
- }
- }
-}
-
-func TestFieldByIndexNil(t *testing.T) {
- type P struct {
- F int
- }
- type T struct {
- *P
- }
- v := ValueOf(T{})
-
- v.FieldByName("P") // should be fine
-
- defer func() {
- if err := recover(); err == nil {
- t.Fatalf("no error")
- } else if !strings.Contains(fmt.Sprint(err), "nil pointer to embedded struct") {
- t.Fatalf(`err=%q, wanted error containing "nil pointer to embedded struct"`, err)
- }
- }()
- v.FieldByName("F") // should panic
-
- t.Fatalf("did not panic")
-}
-
-// Given
-// type Outer struct {
-// *Inner
-// ...
-// }
-// the compiler generates the implementation of (*Outer).M dispatching to the embedded Inner.
-// The implementation is logically:
-// func (p *Outer) M() {
-// (p.Inner).M()
-// }
-// but since the only change here is the replacement of one pointer receiver with another,
-// the actual generated code overwrites the original receiver with the p.Inner pointer and
-// then jumps to the M method expecting the *Inner receiver.
-//
-// During reflect.Value.Call, we create an argument frame and the associated data structures
-// to describe it to the garbage collector, populate the frame, call reflect.call to
-// run a function call using that frame, and then copy the results back out of the frame.
-// The reflect.call function does a memmove of the frame structure onto the
-// stack (to set up the inputs), runs the call, and the memmoves the stack back to
-// the frame structure (to preserve the outputs).
-//
-// Originally reflect.call did not distinguish inputs from outputs: both memmoves
-// were for the full stack frame. However, in the case where the called function was
-// one of these wrappers, the rewritten receiver is almost certainly a different type
-// than the original receiver. This is not a problem on the stack, where we use the
-// program counter to determine the type information and understand that
-// during (*Outer).M the receiver is an *Outer while during (*Inner).M the receiver in the same
-// memory word is now an *Inner. But in the statically typed argument frame created
-// by reflect, the receiver is always an *Outer. Copying the modified receiver pointer
-// off the stack into the frame will store an *Inner there, and then if a garbage collection
-// happens to scan that argument frame before it is discarded, it will scan the *Inner
-// memory as if it were an *Outer. If the two have different memory layouts, the
-// collection will intepret the memory incorrectly.
-//
-// One such possible incorrect interpretation is to treat two arbitrary memory words
-// (Inner.P1 and Inner.P2 below) as an interface (Outer.R below). Because interpreting
-// an interface requires dereferencing the itab word, the misinterpretation will try to
-// deference Inner.P1, causing a crash during garbage collection.
-//
-// This came up in a real program in issue 7725.
-
-type Outer struct {
- *Inner
- R io.Reader
-}
-
-type Inner struct {
- X *Outer
- P1 uintptr
- P2 uintptr
-}
-
-func (pi *Inner) M() {
- // Clear references to pi so that the only way the
- // garbage collection will find the pointer is in the
- // argument frame, typed as a *Outer.
- pi.X.Inner = nil
-
- // Set up an interface value that will cause a crash.
- // P1 = 1 is a non-zero, so the interface looks non-nil.
- // P2 = pi ensures that the data word points into the
- // allocated heap; if not the collection skips the interface
- // value as irrelevant, without dereferencing P1.
- pi.P1 = 1
- pi.P2 = uintptr(unsafe.Pointer(pi))
-}
-
-func TestCallMethodJump(t *testing.T) {
- // In reflect.Value.Call, trigger a garbage collection after reflect.call
- // returns but before the args frame has been discarded.
- // This is a little clumsy but makes the failure repeatable.
- *CallGC = true
-
- p := &Outer{Inner: new(Inner)}
- p.Inner.X = p
- ValueOf(p).Method(0).Call(nil)
-
- // Stop garbage collecting during reflect.call.
- *CallGC = false
-}
diff --git a/src/pkg/reflect/asm_386.s b/src/pkg/reflect/asm_386.s
deleted file mode 100644
index 75413c752..000000000
--- a/src/pkg/reflect/asm_386.s
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#include "../../cmd/ld/textflag.h"
-
-// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
- MOVL DX, 0(SP)
- LEAL argframe+0(FP), CX
- MOVL CX, 4(SP)
- CALL ·callReflect(SB)
- RET
-
-// methodValueCall is the code half of the function returned by makeMethodValue.
-// See the comment on the declaration of methodValueCall in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
- MOVL DX, 0(SP)
- LEAL argframe+0(FP), CX
- MOVL CX, 4(SP)
- CALL ·callMethod(SB)
- RET
diff --git a/src/pkg/reflect/asm_amd64.s b/src/pkg/reflect/asm_amd64.s
deleted file mode 100644
index 712959843..000000000
--- a/src/pkg/reflect/asm_amd64.s
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#include "../../cmd/ld/textflag.h"
-
-// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
- MOVQ DX, 0(SP)
- LEAQ argframe+0(FP), CX
- MOVQ CX, 8(SP)
- CALL ·callReflect(SB)
- RET
-
-// methodValueCall is the code half of the function returned by makeMethodValue.
-// See the comment on the declaration of methodValueCall in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
- MOVQ DX, 0(SP)
- LEAQ argframe+0(FP), CX
- MOVQ CX, 8(SP)
- CALL ·callMethod(SB)
- RET
diff --git a/src/pkg/reflect/asm_amd64p32.s b/src/pkg/reflect/asm_amd64p32.s
deleted file mode 100644
index 75413c752..000000000
--- a/src/pkg/reflect/asm_amd64p32.s
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#include "../../cmd/ld/textflag.h"
-
-// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
- MOVL DX, 0(SP)
- LEAL argframe+0(FP), CX
- MOVL CX, 4(SP)
- CALL ·callReflect(SB)
- RET
-
-// methodValueCall is the code half of the function returned by makeMethodValue.
-// See the comment on the declaration of methodValueCall in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
- MOVL DX, 0(SP)
- LEAL argframe+0(FP), CX
- MOVL CX, 4(SP)
- CALL ·callMethod(SB)
- RET
diff --git a/src/pkg/reflect/asm_arm.s b/src/pkg/reflect/asm_arm.s
deleted file mode 100644
index 68ded4ac6..000000000
--- a/src/pkg/reflect/asm_arm.s
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.
-
-#include "../../cmd/ld/textflag.h"
-
-// makeFuncStub is jumped to by the code generated by MakeFunc.
-// See the comment on the declaration of makeFuncStub in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
- MOVW R7, 4(R13)
- MOVW $argframe+0(FP), R1
- MOVW R1, 8(R13)
- BL ·callReflect(SB)
- RET
-
-// methodValueCall is the code half of the function returned by makeMethodValue.
-// See the comment on the declaration of methodValueCall in makefunc.go
-// for more details.
-// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
- MOVW R7, 4(R13)
- MOVW $argframe+0(FP), R1
- MOVW R1, 8(R13)
- BL ·callMethod(SB)
- RET
diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go
deleted file mode 100644
index f63715c9a..000000000
--- a/src/pkg/reflect/deepequal.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2009 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.
-
-// Deep equality test via reflection
-
-package reflect
-
-// During deepValueEqual, must keep track of checks that are
-// in progress. The comparison algorithm assumes that all
-// checks in progress are true when it reencounters them.
-// Visited comparisons are stored in a map indexed by visit.
-type visit struct {
- a1 uintptr
- a2 uintptr
- typ Type
-}
-
-// Tests for deep equality using reflected types. The map argument tracks
-// comparisons that have already been seen, which allows short circuiting on
-// recursive types.
-func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
- if !v1.IsValid() || !v2.IsValid() {
- return v1.IsValid() == v2.IsValid()
- }
- if v1.Type() != v2.Type() {
- return false
- }
-
- // if depth > 10 { panic("deepValueEqual") } // for debugging
- hard := func(k Kind) bool {
- switch k {
- case Array, Map, Slice, Struct:
- return true
- }
- return false
- }
-
- if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
- addr1 := v1.UnsafeAddr()
- addr2 := v2.UnsafeAddr()
- if addr1 > addr2 {
- // Canonicalize order to reduce number of entries in visited.
- addr1, addr2 = addr2, addr1
- }
-
- // Short circuit if references are identical ...
- if addr1 == addr2 {
- return true
- }
-
- // ... or already seen
- typ := v1.Type()
- v := visit{addr1, addr2, typ}
- if visited[v] {
- return true
- }
-
- // Remember for later.
- visited[v] = true
- }
-
- switch v1.Kind() {
- case Array:
- for i := 0; i < v1.Len(); i++ {
- if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
- return false
- }
- }
- return true
- case Slice:
- if v1.IsNil() != v2.IsNil() {
- return false
- }
- if v1.Len() != v2.Len() {
- return false
- }
- if v1.Pointer() == v2.Pointer() {
- return true
- }
- for i := 0; i < v1.Len(); i++ {
- if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
- return false
- }
- }
- return true
- case Interface:
- if v1.IsNil() || v2.IsNil() {
- return v1.IsNil() == v2.IsNil()
- }
- return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
- case Ptr:
- return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
- case Struct:
- for i, n := 0, v1.NumField(); i < n; i++ {
- if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) {
- return false
- }
- }
- return true
- case Map:
- if v1.IsNil() != v2.IsNil() {
- return false
- }
- if v1.Len() != v2.Len() {
- return false
- }
- if v1.Pointer() == v2.Pointer() {
- return true
- }
- for _, k := range v1.MapKeys() {
- if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
- return false
- }
- }
- return true
- case Func:
- if v1.IsNil() && v2.IsNil() {
- return true
- }
- // Can't do better than this:
- return false
- default:
- // Normal equality suffices
- return valueInterface(v1, false) == valueInterface(v2, false)
- }
-}
-
-// DeepEqual tests for deep equality. It uses normal == equality where
-// possible but will scan elements of arrays, slices, maps, and fields of
-// structs. In maps, keys are compared with == but elements use deep
-// equality. DeepEqual correctly handles recursive types. Functions are equal
-// only if they are both nil.
-// An empty slice is not equal to a nil slice.
-func DeepEqual(a1, a2 interface{}) bool {
- if a1 == nil || a2 == nil {
- return a1 == a2
- }
- v1 := ValueOf(a1)
- v2 := ValueOf(a2)
- if v1.Type() != v2.Type() {
- return false
- }
- return deepValueEqual(v1, v2, make(map[visit]bool), 0)
-}
diff --git a/src/pkg/reflect/example_test.go b/src/pkg/reflect/example_test.go
deleted file mode 100644
index cca28eeec..000000000
--- a/src/pkg/reflect/example_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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_test
-
-import (
- "fmt"
- "reflect"
-)
-
-func ExampleMakeFunc() {
- // swap is the implementation passed to MakeFunc.
- // It must work in terms of reflect.Values so that it is possible
- // to write code without knowing beforehand what the types
- // will be.
- swap := func(in []reflect.Value) []reflect.Value {
- return []reflect.Value{in[1], in[0]}
- }
-
- // makeSwap expects fptr to be a pointer to a nil function.
- // It sets that pointer to a new function created with MakeFunc.
- // When the function is invoked, reflect turns the arguments
- // into Values, calls swap, and then turns swap's result slice
- // into the values returned by the new function.
- makeSwap := func(fptr interface{}) {
- // fptr is a pointer to a function.
- // Obtain the function value itself (likely nil) as a reflect.Value
- // so that we can query its type and then set the value.
- fn := reflect.ValueOf(fptr).Elem()
-
- // Make a function of the right type.
- v := reflect.MakeFunc(fn.Type(), swap)
-
- // Assign it to the value fn represents.
- fn.Set(v)
- }
-
- // Make and call a swap function for ints.
- var intSwap func(int, int) (int, int)
- makeSwap(&intSwap)
- fmt.Println(intSwap(0, 1))
-
- // Make and call a swap function for float64s.
- var floatSwap func(float64, float64) (float64, float64)
- makeSwap(&floatSwap)
- fmt.Println(floatSwap(2.72, 3.14))
-
- // Output:
- // 1 0
- // 3.14 2.72
-}
-
-func ExampleStructTag() {
- type S struct {
- F string `species:"gopher" color:"blue"`
- }
-
- s := S{}
- st := reflect.TypeOf(s)
- field := st.Field(0)
- fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
-
- // Output:
- // blue gopher
-}
diff --git a/src/pkg/reflect/export_test.go b/src/pkg/reflect/export_test.go
deleted file mode 100644
index 0778ad37f..000000000
--- a/src/pkg/reflect/export_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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
-}
-
-var ArrayOf = arrayOf
-var CallGC = &callGC
diff --git a/src/pkg/reflect/makefunc.go b/src/pkg/reflect/makefunc.go
deleted file mode 100644
index 0e61fdea7..000000000
--- a/src/pkg/reflect/makefunc.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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.
-
-// MakeFunc implementation.
-
-package reflect
-
-import (
- "unsafe"
-)
-
-// makeFuncImpl is the closure value implementing the function
-// returned by MakeFunc.
-type makeFuncImpl struct {
- code uintptr
- typ *funcType
- fn func([]Value) []Value
-}
-
-// MakeFunc returns a new function of the given Type
-// that wraps the function fn. When called, that new function
-// does the following:
-//
-// - converts its arguments to a slice of Values.
-// - runs results := fn(args).
-// - returns the results as a slice of Values, one per formal result.
-//
-// The implementation fn can assume that the argument Value slice
-// has the number and type of arguments given by typ.
-// If typ describes a variadic function, the final Value is itself
-// a slice representing the variadic arguments, as in the
-// body of a variadic function. The result Value slice returned by fn
-// must have the number and type of results given by typ.
-//
-// The Value.Call method allows the caller to invoke a typed function
-// in terms of Values; in contrast, MakeFunc allows the caller to implement
-// a typed function in terms of Values.
-//
-// The Examples section of the documentation includes an illustration
-// of how to use MakeFunc to build a swap function for different types.
-//
-func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
- if typ.Kind() != Func {
- panic("reflect: call of MakeFunc with non-Func type")
- }
-
- t := typ.common()
- ftyp := (*funcType)(unsafe.Pointer(t))
-
- // Indirect Go func value (dummy) to obtain
- // actual code address. (A Go func value is a pointer
- // to a C function pointer. http://golang.org/s/go11func.)
- dummy := makeFuncStub
- code := **(**uintptr)(unsafe.Pointer(&dummy))
-
- impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
-
- return Value{t, unsafe.Pointer(impl), 0, flag(Func) << flagKindShift}
-}
-
-// makeFuncStub is an assembly function that is the code half of
-// the function returned from MakeFunc. It expects a *callReflectFunc
-// as its context register, and its job is to invoke callReflect(ctxt, frame)
-// where ctxt is the context register and frame is a pointer to the first
-// word in the passed-in argument frame.
-func makeFuncStub()
-
-type methodValue struct {
- fn uintptr
- method int
- rcvr Value
-}
-
-// makeMethodValue converts v from the rcvr+method index representation
-// of a method value to an actual method func value, which is
-// basically the receiver value with a special bit set, into a true
-// func value - a value holding an actual func. The output is
-// semantically equivalent to the input as far as the user of package
-// reflect can tell, but the true func representation can be handled
-// by code like Convert and Interface and Assign.
-func makeMethodValue(op string, v Value) Value {
- if v.flag&flagMethod == 0 {
- panic("reflect: internal error: invalid use of makeMethodValue")
- }
-
- // Ignoring the flagMethod bit, v describes the receiver, not the method type.
- fl := v.flag & (flagRO | flagAddr | flagIndir)
- fl |= flag(v.typ.Kind()) << flagKindShift
- rcvr := Value{v.typ, v.ptr, v.scalar, fl}
-
- // v.Type returns the actual type of the method value.
- funcType := v.Type().(*rtype)
-
- // Indirect Go func value (dummy) to obtain
- // actual code address. (A Go func value is a pointer
- // to a C function pointer. http://golang.org/s/go11func.)
- dummy := methodValueCall
- code := **(**uintptr)(unsafe.Pointer(&dummy))
-
- fv := &methodValue{
- fn: code,
- method: int(v.flag) >> flagMethodShift,
- rcvr: rcvr,
- }
-
- // Cause panic if method is not appropriate.
- // The panic would still happen during the call if we omit this,
- // but we want Interface() and other operations to fail early.
- methodReceiver(op, fv.rcvr, fv.method)
-
- return Value{funcType, unsafe.Pointer(fv), 0, v.flag&flagRO | flag(Func)<<flagKindShift}
-}
-
-// methodValueCall is an assembly function that is the code half of
-// the function returned from makeMethodValue. It expects a *methodValue
-// as its context register, and its job is to invoke callMethod(ctxt, frame)
-// where ctxt is the context register and frame is a pointer to the first
-// word in the passed-in argument frame.
-func methodValueCall()
diff --git a/src/pkg/reflect/set_test.go b/src/pkg/reflect/set_test.go
deleted file mode 100644
index 85dc55e68..000000000
--- a/src/pkg/reflect/set_test.go
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2011 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_test
-
-import (
- "bytes"
- "go/ast"
- "io"
- . "reflect"
- "testing"
- "unsafe"
-)
-
-type MyBuffer bytes.Buffer
-
-func TestImplicitMapConversion(t *testing.T) {
- // Test implicit conversions in MapIndex and SetMapIndex.
- {
- // direct
- m := make(map[int]int)
- mv := ValueOf(m)
- mv.SetMapIndex(ValueOf(1), ValueOf(2))
- x, ok := m[1]
- if x != 2 {
- t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
- }
- if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
- t.Errorf("#1 MapIndex(1) = %d", n)
- }
- }
- {
- // convert interface key
- m := make(map[interface{}]int)
- mv := ValueOf(m)
- mv.SetMapIndex(ValueOf(1), ValueOf(2))
- x, ok := m[1]
- if x != 2 {
- t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
- }
- if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
- t.Errorf("#2 MapIndex(1) = %d", n)
- }
- }
- {
- // convert interface value
- m := make(map[int]interface{})
- mv := ValueOf(m)
- mv.SetMapIndex(ValueOf(1), ValueOf(2))
- x, ok := m[1]
- if x != 2 {
- t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
- }
- if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
- t.Errorf("#3 MapIndex(1) = %d", n)
- }
- }
- {
- // convert both interface key and interface value
- m := make(map[interface{}]interface{})
- mv := ValueOf(m)
- mv.SetMapIndex(ValueOf(1), ValueOf(2))
- x, ok := m[1]
- if x != 2 {
- t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m)
- }
- if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 {
- t.Errorf("#4 MapIndex(1) = %d", n)
- }
- }
- {
- // convert both, with non-empty interfaces
- m := make(map[io.Reader]io.Writer)
- mv := ValueOf(m)
- b1 := new(bytes.Buffer)
- b2 := new(bytes.Buffer)
- mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
- x, ok := m[b1]
- if x != b2 {
- t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
- }
- if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) {
- t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2)
- }
- }
- {
- // convert channel direction
- m := make(map[<-chan int]chan int)
- mv := ValueOf(m)
- c1 := make(chan int)
- c2 := make(chan int)
- mv.SetMapIndex(ValueOf(c1), ValueOf(c2))
- x, ok := m[c1]
- if x != c2 {
- t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m)
- }
- if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() {
- t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2)
- }
- }
- {
- // convert identical underlying types
- // TODO(rsc): Should be able to define MyBuffer here.
- // 6l prints very strange messages about .this.Bytes etc
- // when we do that though, so MyBuffer is defined
- // at top level.
- m := make(map[*MyBuffer]*bytes.Buffer)
- mv := ValueOf(m)
- b1 := new(MyBuffer)
- b2 := new(bytes.Buffer)
- mv.SetMapIndex(ValueOf(b1), ValueOf(b2))
- x, ok := m[b1]
- if x != b2 {
- t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m)
- }
- if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) {
- t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2)
- }
- }
-
-}
-
-func TestImplicitSetConversion(t *testing.T) {
- // Assume TestImplicitMapConversion covered the basics.
- // Just make sure conversions are being applied at all.
- var r io.Reader
- b := new(bytes.Buffer)
- rv := ValueOf(&r).Elem()
- rv.Set(ValueOf(b))
- if r != b {
- t.Errorf("after Set: r=%T(%v)", r, r)
- }
-}
-
-func TestImplicitSendConversion(t *testing.T) {
- c := make(chan io.Reader, 10)
- b := new(bytes.Buffer)
- ValueOf(c).Send(ValueOf(b))
- if bb := <-c; bb != b {
- t.Errorf("Received %p != %p", bb, b)
- }
-}
-
-func TestImplicitCallConversion(t *testing.T) {
- // Arguments must be assignable to parameter types.
- fv := ValueOf(io.WriteString)
- b := new(bytes.Buffer)
- fv.Call([]Value{ValueOf(b), ValueOf("hello world")})
- if b.String() != "hello world" {
- t.Errorf("After call: string=%q want %q", b.String(), "hello world")
- }
-}
-
-func TestImplicitAppendConversion(t *testing.T) {
- // Arguments must be assignable to the slice's element type.
- s := []io.Reader{}
- sv := ValueOf(&s).Elem()
- b := new(bytes.Buffer)
- sv.Set(Append(sv, ValueOf(b)))
- if len(s) != 1 || s[0] != b {
- t.Errorf("after append: s=%v want [%p]", s, b)
- }
-}
-
-var implementsTests = []struct {
- x interface{}
- t interface{}
- b bool
-}{
- {new(*bytes.Buffer), new(io.Reader), true},
- {new(bytes.Buffer), new(io.Reader), false},
- {new(*bytes.Buffer), new(io.ReaderAt), false},
- {new(*ast.Ident), new(ast.Expr), true},
-}
-
-func TestImplements(t *testing.T) {
- for _, tt := range implementsTests {
- xv := TypeOf(tt.x).Elem()
- xt := TypeOf(tt.t).Elem()
- if b := xv.Implements(xt); b != tt.b {
- t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
- }
- }
-}
-
-var assignableTests = []struct {
- x interface{}
- t interface{}
- b bool
-}{
- {new(chan int), new(<-chan int), true},
- {new(<-chan int), new(chan int), false},
- {new(*int), new(IntPtr), true},
- {new(IntPtr), new(*int), true},
- {new(IntPtr), new(IntPtr1), false},
- // test runs implementsTests too
-}
-
-type IntPtr *int
-type IntPtr1 *int
-
-func TestAssignableTo(t *testing.T) {
- for _, tt := range append(assignableTests, implementsTests...) {
- xv := TypeOf(tt.x).Elem()
- xt := TypeOf(tt.t).Elem()
- if b := xv.AssignableTo(xt); b != tt.b {
- t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b)
- }
- }
-}
diff --git a/src/pkg/reflect/tostring_test.go b/src/pkg/reflect/tostring_test.go
deleted file mode 100644
index e416fd84d..000000000
--- a/src/pkg/reflect/tostring_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2009 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.
-
-// Formatting of reflection types and values for debugging.
-// Not defined as methods so they do not need to be linked into most binaries;
-// the functions are not used by the library itself, only in tests.
-
-package reflect_test
-
-import (
- . "reflect"
- "strconv"
-)
-
-// valueToString returns a textual representation of the reflection value val.
-// For debugging only.
-func valueToString(val Value) string {
- var str string
- if !val.IsValid() {
- return "<zero Value>"
- }
- typ := val.Type()
- switch val.Kind() {
- case Int, Int8, Int16, Int32, Int64:
- return strconv.FormatInt(val.Int(), 10)
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return strconv.FormatUint(val.Uint(), 10)
- case Float32, Float64:
- return strconv.FormatFloat(val.Float(), 'g', -1, 64)
- case Complex64, Complex128:
- c := val.Complex()
- return strconv.FormatFloat(real(c), 'g', -1, 64) + "+" + strconv.FormatFloat(imag(c), 'g', -1, 64) + "i"
- case String:
- return val.String()
- case Bool:
- if val.Bool() {
- return "true"
- } else {
- return "false"
- }
- case Ptr:
- v := val
- str = typ.String() + "("
- if v.IsNil() {
- str += "0"
- } else {
- str += "&" + valueToString(v.Elem())
- }
- str += ")"
- return str
- case Array, Slice:
- v := val
- str += typ.String()
- str += "{"
- for i := 0; i < v.Len(); i++ {
- if i > 0 {
- str += ", "
- }
- str += valueToString(v.Index(i))
- }
- str += "}"
- return str
- case Map:
- t := typ
- str = t.String()
- str += "{"
- str += "<can't iterate on maps>"
- str += "}"
- return str
- case Chan:
- str = typ.String()
- return str
- case Struct:
- t := typ
- v := val
- str += t.String()
- str += "{"
- for i, n := 0, v.NumField(); i < n; i++ {
- if i > 0 {
- str += ", "
- }
- str += valueToString(v.Field(i))
- }
- str += "}"
- return str
- case Interface:
- return typ.String() + "(" + valueToString(val.Elem()) + ")"
- case Func:
- v := val
- return typ.String() + "(" + strconv.FormatUint(uint64(v.Pointer()), 10) + ")"
- default:
- panic("valueToString: can't print type " + typ.String())
- }
-}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
deleted file mode 100644
index 40d76f99d..000000000
--- a/src/pkg/reflect/type.go
+++ /dev/null
@@ -1,1926 +0,0 @@
-// Copyright 2009 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 implements run-time reflection, allowing a program to
-// manipulate objects with arbitrary types. The typical use is to take a value
-// with static type interface{} and extract its dynamic type information by
-// calling TypeOf, which returns a Type.
-//
-// A call to ValueOf returns a Value representing the run-time data.
-// Zero takes a Type and returns a Value representing a zero value
-// for that type.
-//
-// See "The Laws of Reflection" for an introduction to reflection in Go:
-// http://golang.org/doc/articles/laws_of_reflection.html
-package reflect
-
-import (
- "runtime"
- "strconv"
- "sync"
- "unsafe"
-)
-
-// Type is the representation of a Go type.
-//
-// Not all methods apply to all kinds of types. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of type before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run-time panic.
-type Type interface {
- // Methods applicable to all types.
-
- // Align returns the alignment in bytes of a value of
- // this type when allocated in memory.
- Align() int
-
- // FieldAlign returns the alignment in bytes of a value of
- // this type when used as a field in a struct.
- FieldAlign() int
-
- // Method returns the i'th method in the type's method set.
- // It panics if i is not in the range [0, NumMethod()).
- //
- // For a non-interface type T or *T, the returned Method's Type and Func
- // fields describe a function whose first argument is the receiver.
- //
- // For an interface type, the returned Method's Type field gives the
- // method signature, without a receiver, and the Func field is nil.
- Method(int) Method
-
- // MethodByName returns the method with that name in the type's
- // method set and a boolean indicating if the method was found.
- //
- // For a non-interface type T or *T, the returned Method's Type and Func
- // fields describe a function whose first argument is the receiver.
- //
- // For an interface type, the returned Method's Type field gives the
- // method signature, without a receiver, and the Func field is nil.
- MethodByName(string) (Method, bool)
-
- // NumMethod returns the number of methods in the type's method set.
- NumMethod() int
-
- // Name returns the type's name within its package.
- // It returns an empty string for unnamed types.
- Name() string
-
- // PkgPath returns a named type's package path, that is, the import path
- // that uniquely identifies the package, such as "encoding/base64".
- // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int),
- // the package path will be the empty string.
- PkgPath() string
-
- // Size returns the number of bytes needed to store
- // a value of the given type; it is analogous to unsafe.Sizeof.
- Size() uintptr
-
- // String returns a string representation of the type.
- // The string representation may use shortened package names
- // (e.g., base64 instead of "encoding/base64") and is not
- // guaranteed to be unique among types. To test for equality,
- // compare the Types directly.
- String() string
-
- // Kind returns the specific kind of this type.
- Kind() Kind
-
- // Implements returns true if the type implements the interface type u.
- Implements(u Type) bool
-
- // AssignableTo returns true if a value of the type is assignable to type u.
- 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.
- // The methods allowed for each kind are:
- //
- // Int*, Uint*, Float*, Complex*: Bits
- // Array: Elem, Len
- // Chan: ChanDir, Elem
- // Func: In, NumIn, Out, NumOut, IsVariadic.
- // Map: Key, Elem
- // Ptr: Elem
- // Slice: Elem
- // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
-
- // Bits returns the size of the type in bits.
- // It panics if the type's Kind is not one of the
- // sized or unsized Int, Uint, Float, or Complex kinds.
- Bits() int
-
- // ChanDir returns a channel type's direction.
- // It panics if the type's Kind is not Chan.
- ChanDir() ChanDir
-
- // IsVariadic returns true if a function type's final input parameter
- // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
- // implicit actual type []T.
- //
- // For concreteness, if t represents func(x int, y ... float64), then
- //
- // t.NumIn() == 2
- // t.In(0) is the reflect.Type for "int"
- // t.In(1) is the reflect.Type for "[]float64"
- // t.IsVariadic() == true
- //
- // IsVariadic panics if the type's Kind is not Func.
- IsVariadic() bool
-
- // Elem returns a type's element type.
- // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
- Elem() Type
-
- // Field returns a struct type's i'th field.
- // It panics if the type's Kind is not Struct.
- // It panics if i is not in the range [0, NumField()).
- Field(i int) StructField
-
- // FieldByIndex returns the nested field corresponding
- // to the index sequence. It is equivalent to calling Field
- // successively for each index i.
- // It panics if the type's Kind is not Struct.
- FieldByIndex(index []int) StructField
-
- // FieldByName returns the struct field with the given name
- // and a boolean indicating if the field was found.
- FieldByName(name string) (StructField, bool)
-
- // FieldByNameFunc returns the first struct field with a name
- // that satisfies the match function and a boolean indicating if
- // the field was found.
- FieldByNameFunc(match func(string) bool) (StructField, bool)
-
- // In returns the type of a function type's i'th input parameter.
- // It panics if the type's Kind is not Func.
- // It panics if i is not in the range [0, NumIn()).
- In(i int) Type
-
- // Key returns a map type's key type.
- // It panics if the type's Kind is not Map.
- Key() Type
-
- // Len returns an array type's length.
- // It panics if the type's Kind is not Array.
- Len() int
-
- // NumField returns a struct type's field count.
- // It panics if the type's Kind is not Struct.
- NumField() int
-
- // NumIn returns a function type's input parameter count.
- // It panics if the type's Kind is not Func.
- NumIn() int
-
- // NumOut returns a function type's output parameter count.
- // It panics if the type's Kind is not Func.
- NumOut() int
-
- // Out returns the type of a function type's i'th output parameter.
- // It panics if the type's Kind is not Func.
- // It panics if i is not in the range [0, NumOut()).
- Out(i int) Type
-
- common() *rtype
- uncommon() *uncommonType
-}
-
-// BUG(rsc): FieldByName and related functions consider struct field names to be equal
-// if the names are equal, even if they are unexported names originating
-// in different packages. The practical effect of this is that the result of
-// t.FieldByName("x") is not well defined if the struct type t contains
-// multiple fields named x (embedded from different packages).
-// FieldByName may return one of the fields named x or may report that there are none.
-// See golang.org/issue/4876 for more details.
-
-/*
- * These data structures are known to the compiler (../../cmd/gc/reflect.c).
- * A few are known to ../runtime/type.go to convey to debuggers.
- * They are also known to ../runtime/type.h.
- */
-
-// A Kind represents the specific kind of type that a Type represents.
-// The zero Kind is not a valid kind.
-type Kind uint
-
-const (
- Invalid Kind = iota
- Bool
- Int
- Int8
- Int16
- Int32
- Int64
- Uint
- Uint8
- Uint16
- Uint32
- Uint64
- Uintptr
- Float32
- Float64
- Complex64
- Complex128
- Array
- Chan
- Func
- Interface
- Map
- Ptr
- Slice
- String
- Struct
- UnsafePointer
-)
-
-// rtype is the common implementation of most values.
-// It is embedded in other, public struct types, but always
-// with a unique tag like `reflect:"array"` or `reflect:"ptr"`
-// so that code cannot convert from, say, *arrayType to *ptrType.
-type rtype struct {
- size uintptr // size in bytes
- hash uint32 // hash of type; avoids computation in hash tables
- _ uint8 // unused/padding
- align uint8 // alignment of variable with this type
- fieldAlign uint8 // alignment of struct field with this type
- kind uint8 // enumeration for C
- alg *uintptr // algorithm table (../runtime/runtime.h:/Alg)
- gc unsafe.Pointer // garbage collection data
- string *string // string form; unnecessary but undeniably useful
- *uncommonType // (relatively) uncommon fields
- ptrToThis *rtype // type for pointer to this type, if used in binary or has methods
- zero unsafe.Pointer // pointer to zero value
-}
-
-// Method on non-interface type
-type method struct {
- name *string // name of method
- pkgPath *string // nil for exported Names; otherwise import path
- mtyp *rtype // method type (without receiver)
- typ *rtype // .(*FuncType) underneath (with receiver)
- ifn unsafe.Pointer // fn used in interface call (one-word receiver)
- tfn unsafe.Pointer // fn used for normal method call
-}
-
-// uncommonType is present only for types with names or methods
-// (if T is a named type, the uncommonTypes for T and *T have methods).
-// Using a pointer to this struct reduces the overall size required
-// to describe an unnamed type with no methods.
-type uncommonType struct {
- name *string // name of type
- pkgPath *string // import path; nil for built-in types like int, string
- methods []method // methods associated with type
-}
-
-// ChanDir represents a channel type's direction.
-type ChanDir int
-
-const (
- RecvDir ChanDir = 1 << iota // <-chan
- SendDir // chan<-
- BothDir = RecvDir | SendDir // chan
-)
-
-// arrayType represents a fixed array type.
-type arrayType struct {
- rtype `reflect:"array"`
- elem *rtype // array element type
- slice *rtype // slice type
- len uintptr
-}
-
-// chanType represents a channel type.
-type chanType struct {
- rtype `reflect:"chan"`
- elem *rtype // channel element type
- dir uintptr // channel direction (ChanDir)
-}
-
-// funcType represents a function type.
-type funcType struct {
- rtype `reflect:"func"`
- dotdotdot bool // last input parameter is ...
- in []*rtype // input parameter types
- out []*rtype // output parameter types
-}
-
-// imethod represents a method on an interface type
-type imethod struct {
- name *string // name of method
- pkgPath *string // nil for exported Names; otherwise import path
- typ *rtype // .(*FuncType) underneath
-}
-
-// interfaceType represents an interface type.
-type interfaceType struct {
- rtype `reflect:"interface"`
- methods []imethod // sorted by hash
-}
-
-// mapType represents a map type.
-type mapType struct {
- rtype `reflect:"map"`
- key *rtype // map key type
- elem *rtype // map element (value) type
- bucket *rtype // internal bucket structure
- hmap *rtype // internal map header
-}
-
-// ptrType represents a pointer type.
-type ptrType struct {
- rtype `reflect:"ptr"`
- elem *rtype // pointer element (pointed at) type
-}
-
-// sliceType represents a slice type.
-type sliceType struct {
- rtype `reflect:"slice"`
- elem *rtype // slice element type
-}
-
-// Struct field
-type structField struct {
- name *string // nil for embedded fields
- pkgPath *string // nil for exported Names; otherwise import path
- typ *rtype // type of field
- tag *string // nil if no tag
- offset uintptr // byte offset of field within struct
-}
-
-// structType represents a struct type.
-type structType struct {
- rtype `reflect:"struct"`
- fields []structField // sorted by offset
-}
-
-// NOTE: These are copied from ../runtime/mgc0.h.
-// They must be kept in sync.
-const (
- _GC_END = iota
- _GC_PTR
- _GC_APTR
- _GC_ARRAY_START
- _GC_ARRAY_NEXT
- _GC_CALL
- _GC_CHAN_PTR
- _GC_STRING
- _GC_EFACE
- _GC_IFACE
- _GC_SLICE
- _GC_REGION
- _GC_NUM_INSTR
-)
-
-/*
- * The compiler knows the exact layout of all the data structures above.
- * The compiler does not know about the data structures and methods below.
- */
-
-// Method represents a single method.
-type Method struct {
- // Name is the method name.
- // PkgPath is the package path that qualifies a lower case (unexported)
- // method name. It is empty for upper case (exported) method names.
- // The combination of PkgPath and Name uniquely identifies a method
- // in a method set.
- // See http://golang.org/ref/spec#Uniqueness_of_identifiers
- Name string
- PkgPath string
-
- Type Type // method type
- Func Value // func with receiver as first argument
- Index int // index for Type.Method
-}
-
-// High bit says whether type has
-// embedded pointers,to help garbage collector.
-const (
- kindMask = 0x7f
- kindNoPointers = 0x80
-)
-
-func (k Kind) String() string {
- if int(k) < len(kindNames) {
- return kindNames[k]
- }
- return "kind" + strconv.Itoa(int(k))
-}
-
-var kindNames = []string{
- Invalid: "invalid",
- Bool: "bool",
- Int: "int",
- Int8: "int8",
- Int16: "int16",
- Int32: "int32",
- Int64: "int64",
- Uint: "uint",
- Uint8: "uint8",
- Uint16: "uint16",
- Uint32: "uint32",
- Uint64: "uint64",
- Uintptr: "uintptr",
- Float32: "float32",
- Float64: "float64",
- Complex64: "complex64",
- Complex128: "complex128",
- Array: "array",
- Chan: "chan",
- Func: "func",
- Interface: "interface",
- Map: "map",
- Ptr: "ptr",
- Slice: "slice",
- String: "string",
- Struct: "struct",
- UnsafePointer: "unsafe.Pointer",
-}
-
-func (t *uncommonType) uncommon() *uncommonType {
- return t
-}
-
-func (t *uncommonType) PkgPath() string {
- if t == nil || t.pkgPath == nil {
- return ""
- }
- return *t.pkgPath
-}
-
-func (t *uncommonType) Name() string {
- if t == nil || t.name == nil {
- return ""
- }
- return *t.name
-}
-
-func (t *rtype) String() string { return *t.string }
-
-func (t *rtype) Size() uintptr { return t.size }
-
-func (t *rtype) Bits() int {
- if t == nil {
- panic("reflect: Bits of nil Type")
- }
- k := t.Kind()
- if k < Int || k > Complex128 {
- panic("reflect: Bits of non-arithmetic Type " + t.String())
- }
- return int(t.size) * 8
-}
-
-func (t *rtype) Align() int { return int(t.align) }
-
-func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
-
-func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
-
-func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 }
-
-func (t *rtype) common() *rtype { return t }
-
-func (t *uncommonType) Method(i int) (m Method) {
- if t == nil || i < 0 || i >= len(t.methods) {
- panic("reflect: Method index out of range")
- }
- p := &t.methods[i]
- if p.name != nil {
- m.Name = *p.name
- }
- fl := flag(Func) << flagKindShift
- if p.pkgPath != nil {
- m.PkgPath = *p.pkgPath
- fl |= flagRO
- }
- mt := p.typ
- m.Type = mt
- fn := unsafe.Pointer(&p.tfn)
- m.Func = Value{mt, fn, 0, fl}
- m.Index = i
- return
-}
-
-func (t *uncommonType) NumMethod() int {
- if t == nil {
- return 0
- }
- return len(t.methods)
-}
-
-func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
- if t == nil {
- return
- }
- var p *method
- for i := range t.methods {
- p = &t.methods[i]
- if p.name != nil && *p.name == name {
- return t.Method(i), true
- }
- }
- return
-}
-
-// TODO(rsc): 6g supplies these, but they are not
-// as efficient as they could be: they have commonType
-// as the receiver instead of *rtype.
-func (t *rtype) NumMethod() int {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.NumMethod()
- }
- return t.uncommonType.NumMethod()
-}
-
-func (t *rtype) Method(i int) (m Method) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.Method(i)
- }
- return t.uncommonType.Method(i)
-}
-
-func (t *rtype) MethodByName(name string) (m Method, ok bool) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.MethodByName(name)
- }
- return t.uncommonType.MethodByName(name)
-}
-
-func (t *rtype) PkgPath() string {
- return t.uncommonType.PkgPath()
-}
-
-func (t *rtype) Name() string {
- return t.uncommonType.Name()
-}
-
-func (t *rtype) ChanDir() ChanDir {
- if t.Kind() != Chan {
- panic("reflect: ChanDir of non-chan type")
- }
- tt := (*chanType)(unsafe.Pointer(t))
- return ChanDir(tt.dir)
-}
-
-func (t *rtype) IsVariadic() bool {
- if t.Kind() != Func {
- panic("reflect: IsVariadic of non-func type")
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return tt.dotdotdot
-}
-
-func (t *rtype) Elem() Type {
- switch t.Kind() {
- case Array:
- tt := (*arrayType)(unsafe.Pointer(t))
- return toType(tt.elem)
- case Chan:
- tt := (*chanType)(unsafe.Pointer(t))
- return toType(tt.elem)
- case Map:
- tt := (*mapType)(unsafe.Pointer(t))
- return toType(tt.elem)
- case Ptr:
- tt := (*ptrType)(unsafe.Pointer(t))
- return toType(tt.elem)
- case Slice:
- tt := (*sliceType)(unsafe.Pointer(t))
- return toType(tt.elem)
- }
- panic("reflect: Elem of invalid type")
-}
-
-func (t *rtype) Field(i int) StructField {
- if t.Kind() != Struct {
- panic("reflect: Field of non-struct type")
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.Field(i)
-}
-
-func (t *rtype) FieldByIndex(index []int) StructField {
- if t.Kind() != Struct {
- panic("reflect: FieldByIndex of non-struct type")
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByIndex(index)
-}
-
-func (t *rtype) FieldByName(name string) (StructField, bool) {
- if t.Kind() != Struct {
- panic("reflect: FieldByName of non-struct type")
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByName(name)
-}
-
-func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
- if t.Kind() != Struct {
- panic("reflect: FieldByNameFunc of non-struct type")
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByNameFunc(match)
-}
-
-func (t *rtype) In(i int) Type {
- if t.Kind() != Func {
- panic("reflect: In of non-func type")
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.in[i])
-}
-
-func (t *rtype) Key() Type {
- if t.Kind() != Map {
- panic("reflect: Key of non-map type")
- }
- tt := (*mapType)(unsafe.Pointer(t))
- return toType(tt.key)
-}
-
-func (t *rtype) Len() int {
- if t.Kind() != Array {
- panic("reflect: Len of non-array type")
- }
- tt := (*arrayType)(unsafe.Pointer(t))
- return int(tt.len)
-}
-
-func (t *rtype) NumField() int {
- if t.Kind() != Struct {
- panic("reflect: NumField of non-struct type")
- }
- tt := (*structType)(unsafe.Pointer(t))
- return len(tt.fields)
-}
-
-func (t *rtype) NumIn() int {
- if t.Kind() != Func {
- panic("reflect: NumIn of non-func type")
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return len(tt.in)
-}
-
-func (t *rtype) NumOut() int {
- if t.Kind() != Func {
- panic("reflect: NumOut of non-func type")
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return len(tt.out)
-}
-
-func (t *rtype) Out(i int) Type {
- if t.Kind() != Func {
- panic("reflect: Out of non-func type")
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.out[i])
-}
-
-func (d ChanDir) String() string {
- switch d {
- case SendDir:
- return "chan<-"
- case RecvDir:
- return "<-chan"
- case BothDir:
- return "chan"
- }
- return "ChanDir" + strconv.Itoa(int(d))
-}
-
-// Method returns the i'th method in the type's method set.
-func (t *interfaceType) Method(i int) (m Method) {
- if i < 0 || i >= len(t.methods) {
- return
- }
- p := &t.methods[i]
- m.Name = *p.name
- if p.pkgPath != nil {
- m.PkgPath = *p.pkgPath
- }
- m.Type = toType(p.typ)
- m.Index = i
- return
-}
-
-// NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.methods) }
-
-// MethodByName method with the given name in the type's method set.
-func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
- if t == nil {
- return
- }
- var p *imethod
- for i := range t.methods {
- p = &t.methods[i]
- if *p.name == name {
- return t.Method(i), true
- }
- }
- return
-}
-
-// A StructField describes a single field in a struct.
-type StructField struct {
- // Name is the field name.
- // PkgPath is the package path that qualifies a lower case (unexported)
- // field name. It is empty for upper case (exported) field names.
- // See http://golang.org/ref/spec#Uniqueness_of_identifiers
- Name string
- PkgPath string
-
- Type Type // field type
- Tag StructTag // field tag string
- Offset uintptr // offset within struct, in bytes
- Index []int // index sequence for Type.FieldByIndex
- Anonymous bool // is an embedded field
-}
-
-// A StructTag is the tag string in a struct field.
-//
-// By convention, tag strings are a concatenation of
-// optionally space-separated key:"value" pairs.
-// Each key is a non-empty string consisting of non-control
-// characters other than space (U+0020 ' '), quote (U+0022 '"'),
-// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
-// characters and Go string literal syntax.
-type StructTag string
-
-// Get returns the value associated with key in the tag string.
-// If there is no such key in the tag, Get returns the empty string.
-// If the tag does not have the conventional format, the value
-// returned by Get is unspecified.
-func (tag StructTag) Get(key string) string {
- for tag != "" {
- // skip leading space
- i := 0
- for i < len(tag) && tag[i] == ' ' {
- i++
- }
- tag = tag[i:]
- if tag == "" {
- break
- }
-
- // scan to colon.
- // a space or a quote is a syntax error
- i = 0
- for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
- i++
- }
- if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
- break
- }
- name := string(tag[:i])
- tag = tag[i+1:]
-
- // scan quoted string to find value
- i = 1
- for i < len(tag) && tag[i] != '"' {
- if tag[i] == '\\' {
- i++
- }
- i++
- }
- if i >= len(tag) {
- break
- }
- qvalue := string(tag[:i+1])
- tag = tag[i+1:]
-
- if key == name {
- value, _ := strconv.Unquote(qvalue)
- return value
- }
- }
- return ""
-}
-
-// Field returns the i'th struct field.
-func (t *structType) Field(i int) (f StructField) {
- if i < 0 || i >= len(t.fields) {
- return
- }
- p := &t.fields[i]
- f.Type = toType(p.typ)
- if p.name != nil {
- f.Name = *p.name
- } else {
- t := f.Type
- if t.Kind() == Ptr {
- t = t.Elem()
- }
- f.Name = t.Name()
- f.Anonymous = true
- }
- if p.pkgPath != nil {
- f.PkgPath = *p.pkgPath
- }
- if p.tag != nil {
- f.Tag = StructTag(*p.tag)
- }
- f.Offset = p.offset
-
- // NOTE(rsc): This is the only allocation in the interface
- // presented by a reflect.Type. It would be nice to avoid,
- // at least in the common cases, but we need to make sure
- // that misbehaving clients of reflect cannot affect other
- // uses of reflect. One possibility is CL 5371098, but we
- // postponed that ugliness until there is a demonstrated
- // need for the performance. This is issue 2320.
- f.Index = []int{i}
- return
-}
-
-// TODO(gri): Should there be an error/bool indicator if the index
-// is wrong for FieldByIndex?
-
-// FieldByIndex returns the nested field corresponding to index.
-func (t *structType) FieldByIndex(index []int) (f StructField) {
- f.Type = toType(&t.rtype)
- for i, x := range index {
- if i > 0 {
- ft := f.Type
- if ft.Kind() == Ptr && ft.Elem().Kind() == Struct {
- ft = ft.Elem()
- }
- f.Type = ft
- }
- f = f.Type.Field(x)
- }
- return
-}
-
-// A fieldScan represents an item on the fieldByNameFunc scan work list.
-type fieldScan struct {
- typ *structType
- index []int
-}
-
-// FieldByNameFunc returns the struct field with a name that satisfies the
-// match function and a boolean to indicate if the field was found.
-func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
- // This uses the same condition that the Go language does: there must be a unique instance
- // of the match at a given depth level. If there are multiple instances of a match at the
- // same depth, they annihilate each other and inhibit any possible match at a lower level.
- // The algorithm is breadth first search, one depth level at a time.
-
- // The current and next slices are work queues:
- // current lists the fields to visit on this depth level,
- // and next lists the fields on the next lower level.
- current := []fieldScan{}
- next := []fieldScan{{typ: t}}
-
- // nextCount records the number of times an embedded type has been
- // encountered and considered for queueing in the 'next' slice.
- // We only queue the first one, but we increment the count on each.
- // If a struct type T can be reached more than once at a given depth level,
- // then it annihilates itself and need not be considered at all when we
- // process that next depth level.
- var nextCount map[*structType]int
-
- // visited records the structs that have been considered already.
- // Embedded pointer fields can create cycles in the graph of
- // reachable embedded types; visited avoids following those cycles.
- // It also avoids duplicated effort: if we didn't find the field in an
- // embedded type T at level 2, we won't find it in one at level 4 either.
- visited := map[*structType]bool{}
-
- for len(next) > 0 {
- current, next = next, current[:0]
- count := nextCount
- nextCount = nil
-
- // Process all the fields at this depth, now listed in 'current'.
- // The loop queues embedded fields found in 'next', for processing during the next
- // iteration. The multiplicity of the 'current' field counts is recorded
- // in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
- for _, scan := range current {
- t := scan.typ
- if visited[t] {
- // We've looked through this type before, at a higher level.
- // That higher level would shadow the lower level we're now at,
- // so this one can't be useful to us. Ignore it.
- continue
- }
- visited[t] = true
- for i := range t.fields {
- f := &t.fields[i]
- // Find name and type for field f.
- var fname string
- var ntyp *rtype
- if f.name != nil {
- fname = *f.name
- } else {
- // Anonymous field of type T or *T.
- // Name taken from type.
- ntyp = f.typ
- if ntyp.Kind() == Ptr {
- ntyp = ntyp.Elem().common()
- }
- fname = ntyp.Name()
- }
-
- // Does it match?
- if match(fname) {
- // Potential match
- if count[t] > 1 || ok {
- // Name appeared multiple times at this level: annihilate.
- return StructField{}, false
- }
- result = t.Field(i)
- result.Index = nil
- result.Index = append(result.Index, scan.index...)
- result.Index = append(result.Index, i)
- ok = true
- continue
- }
-
- // Queue embedded struct fields for processing with next level,
- // but only if we haven't seen a match yet at this level and only
- // if the embedded types haven't already been queued.
- if ok || ntyp == nil || ntyp.Kind() != Struct {
- continue
- }
- styp := (*structType)(unsafe.Pointer(ntyp))
- if nextCount[styp] > 0 {
- nextCount[styp] = 2 // exact multiple doesn't matter
- continue
- }
- if nextCount == nil {
- nextCount = map[*structType]int{}
- }
- nextCount[styp] = 1
- if count[t] > 1 {
- nextCount[styp] = 2 // exact multiple doesn't matter
- }
- var index []int
- index = append(index, scan.index...)
- index = append(index, i)
- next = append(next, fieldScan{styp, index})
- }
- }
- if ok {
- break
- }
- }
- return
-}
-
-// FieldByName returns the struct field with the given name
-// and a boolean to indicate if the field was found.
-func (t *structType) FieldByName(name string) (f StructField, present bool) {
- // Quick check for top-level name, or struct without anonymous fields.
- hasAnon := false
- if name != "" {
- for i := range t.fields {
- tf := &t.fields[i]
- if tf.name == nil {
- hasAnon = true
- continue
- }
- if *tf.name == name {
- return t.Field(i), true
- }
- }
- }
- if !hasAnon {
- return
- }
- return t.FieldByNameFunc(func(s string) bool { return s == name })
-}
-
-// TypeOf returns the reflection Type of the value in the interface{}.
-// TypeOf(nil) returns nil.
-func TypeOf(i interface{}) Type {
- eface := *(*emptyInterface)(unsafe.Pointer(&i))
- return toType(eface.typ)
-}
-
-// ptrMap is the cache for PtrTo.
-var ptrMap struct {
- sync.RWMutex
- m map[*rtype]*ptrType
-}
-
-// garbage collection bytecode program for pointer to memory without pointers.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type ptrDataGC struct {
- width uintptr // sizeof(ptr)
- op uintptr // _GC_APTR
- off uintptr // 0
- end uintptr // _GC_END
-}
-
-var ptrDataGCProg = ptrDataGC{
- width: unsafe.Sizeof((*byte)(nil)),
- op: _GC_APTR,
- off: 0,
- end: _GC_END,
-}
-
-// garbage collection bytecode program for pointer to memory with pointers.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type ptrGC struct {
- width uintptr // sizeof(ptr)
- op uintptr // _GC_PTR
- off uintptr // 0
- elemgc unsafe.Pointer // element gc type
- end uintptr // _GC_END
-}
-
-// PtrTo returns the pointer type with element t.
-// For example, if t represents type Foo, PtrTo(t) represents *Foo.
-func PtrTo(t Type) Type {
- return t.(*rtype).ptrTo()
-}
-
-func (t *rtype) ptrTo() *rtype {
- if p := t.ptrToThis; p != nil {
- return p
- }
-
- // Otherwise, synthesize one.
- // This only happens for pointers with no methods.
- // We keep the mapping in a map on the side, because
- // this operation is rare and a separate map lets us keep
- // the type structures in read-only memory.
- ptrMap.RLock()
- if m := ptrMap.m; m != nil {
- if p := m[t]; p != nil {
- ptrMap.RUnlock()
- return &p.rtype
- }
- }
- ptrMap.RUnlock()
- ptrMap.Lock()
- if ptrMap.m == nil {
- ptrMap.m = make(map[*rtype]*ptrType)
- }
- p := ptrMap.m[t]
- if p != nil {
- // some other goroutine won the race and created it
- ptrMap.Unlock()
- return &p.rtype
- }
-
- // Create a new ptrType starting with the description
- // of an *unsafe.Pointer.
- p = new(ptrType)
- var iptr interface{} = (*unsafe.Pointer)(nil)
- prototype := *(**ptrType)(unsafe.Pointer(&iptr))
- *p = *prototype
-
- s := "*" + *t.string
- p.string = &s
-
- // For the type structures linked into the binary, the
- // compiler provides a good hash of the string.
- // Create a good hash for the new string by using
- // the FNV-1 hash's mixing function to combine the
- // old hash and the new "*".
- p.hash = fnv1(t.hash, '*')
-
- p.uncommonType = nil
- p.ptrToThis = nil
- p.zero = unsafe.Pointer(&make([]byte, p.size)[0])
- p.elem = t
-
- if t.kind&kindNoPointers != 0 {
- p.gc = unsafe.Pointer(&ptrDataGCProg)
- } else {
- p.gc = unsafe.Pointer(&ptrGC{
- width: p.size,
- op: _GC_PTR,
- off: 0,
- elemgc: t.gc,
- end: _GC_END,
- })
- }
- // INCORRECT. Uncomment to check that TestPtrToGC fails when p.gc is wrong.
- //p.gc = unsafe.Pointer(&badGC{width: p.size, end: _GC_END})
-
- ptrMap.m[t] = p
- ptrMap.Unlock()
- return &p.rtype
-}
-
-// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
-func fnv1(x uint32, list ...byte) uint32 {
- for _, b := range list {
- x = x*16777619 ^ uint32(b)
- }
- return x
-}
-
-func (t *rtype) Implements(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.Implements")
- }
- if u.Kind() != Interface {
- panic("reflect: non-interface type passed to Type.Implements")
- }
- return implements(u.(*rtype), t)
-}
-
-func (t *rtype) AssignableTo(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.AssignableTo")
- }
- uu := u.(*rtype)
- return directlyAssignable(uu, t) || implements(uu, t)
-}
-
-func (t *rtype) ConvertibleTo(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.ConvertibleTo")
- }
- uu := u.(*rtype)
- return convertOp(uu, t) != nil
-}
-
-// implements returns true if the type V implements the interface type T.
-func implements(T, V *rtype) bool {
- if T.Kind() != Interface {
- return false
- }
- t := (*interfaceType)(unsafe.Pointer(T))
- if len(t.methods) == 0 {
- return true
- }
-
- // The same algorithm applies in both cases, but the
- // method tables for an interface type and a concrete type
- // are different, so the code is duplicated.
- // In both cases the algorithm is a linear scan over the two
- // lists - T's methods and V's methods - simultaneously.
- // Since method tables are stored in a unique sorted order
- // (alphabetical, with no duplicate method names), the scan
- // through V's methods must hit a match for each of T's
- // methods along the way, or else V does not implement T.
- // This lets us run the scan in overall linear time instead of
- // the quadratic time a naive search would require.
- // See also ../runtime/iface.c.
- if V.Kind() == Interface {
- v := (*interfaceType)(unsafe.Pointer(V))
- i := 0
- for j := 0; j < len(v.methods); j++ {
- tm := &t.methods[i]
- vm := &v.methods[j]
- if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.typ == tm.typ {
- if i++; i >= len(t.methods) {
- return true
- }
- }
- }
- return false
- }
-
- v := V.uncommon()
- if v == nil {
- return false
- }
- i := 0
- for j := 0; j < len(v.methods); j++ {
- tm := &t.methods[i]
- vm := &v.methods[j]
- if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.mtyp == tm.typ {
- if i++; i >= len(t.methods) {
- return true
- }
- }
- }
- return false
-}
-
-// directlyAssignable returns true if a value x of type V can be directly
-// assigned (using memmove) to a value of type T.
-// http://golang.org/doc/go_spec.html#Assignability
-// Ignoring the interface rules (implemented elsewhere)
-// and the ideal constant rules (no ideal constants at run time).
-func directlyAssignable(T, V *rtype) bool {
- // x's type V is identical to T?
- if T == V {
- return true
- }
-
- // Otherwise at least one of T and V must be unnamed
- // and they must have the same kind.
- if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
- return false
- }
-
- // x's type T and V must have identical underlying types.
- return haveIdenticalUnderlyingType(T, V)
-}
-
-func haveIdenticalUnderlyingType(T, V *rtype) 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:
- return T.Elem() == V.Elem() && T.Len() == V.Len()
-
- case Chan:
- // Special case:
- // x is a bidirectional channel value, T is a channel type,
- // and x's type V and T have identical element types.
- if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
- return true
- }
-
- // Otherwise continue test for identical underlying type.
- return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
-
- case Func:
- t := (*funcType)(unsafe.Pointer(T))
- v := (*funcType)(unsafe.Pointer(V))
- if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
- return false
- }
- for i, typ := range t.in {
- if typ != v.in[i] {
- return false
- }
- }
- for i, typ := range t.out {
- if typ != v.out[i] {
- return false
- }
- }
- return true
-
- case Interface:
- t := (*interfaceType)(unsafe.Pointer(T))
- v := (*interfaceType)(unsafe.Pointer(V))
- if len(t.methods) == 0 && len(v.methods) == 0 {
- return true
- }
- // Might have the same methods but still
- // need a run time conversion.
- return false
-
- case Map:
- return T.Key() == V.Key() && T.Elem() == V.Elem()
-
- case Ptr, Slice:
- return T.Elem() == V.Elem()
-
- case Struct:
- t := (*structType)(unsafe.Pointer(T))
- v := (*structType)(unsafe.Pointer(V))
- if len(t.fields) != len(v.fields) {
- return false
- }
- for i := range t.fields {
- tf := &t.fields[i]
- vf := &v.fields[i]
- if tf.name != vf.name && (tf.name == nil || vf.name == nil || *tf.name != *vf.name) {
- return false
- }
- if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) {
- return false
- }
- if tf.typ != vf.typ {
- return false
- }
- if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
- return false
- }
- if tf.offset != vf.offset {
- return false
- }
- }
- return true
- }
-
- return false
-}
-
-// typelinks is implemented in package runtime.
-// It returns a slice of all the 'typelink' information in the binary,
-// which is to say a slice of known types, sorted by string.
-// Note that strings are not unique identifiers for types:
-// there can be more than one with a given string.
-// Only types we might want to look up are included:
-// channels, maps, slices, and arrays.
-func typelinks() []*rtype
-
-// typesByString returns the subslice of typelinks() whose elements have
-// the given string representation.
-// It may be empty (no known types with that string) or may have
-// multiple elements (multiple types with that string).
-func typesByString(s string) []*rtype {
- typ := typelinks()
-
- // We are looking for the first index i where the string becomes >= s.
- // This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s).
- i, j := 0, len(typ)
- for i < j {
- h := i + (j-i)/2 // avoid overflow when computing h
- // i ≤ h < j
- if !(*typ[h].string >= s) {
- i = h + 1 // preserves f(i-1) == false
- } else {
- j = h // preserves f(j) == true
- }
- }
- // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
-
- // Having found the first, linear scan forward to find the last.
- // We could do a second binary search, but the caller is going
- // to do a linear scan anyway.
- j = i
- for j < len(typ) && *typ[j].string == s {
- j++
- }
-
- // This slice will be empty if the string is not found.
- return typ[i:j]
-}
-
-// The lookupCache caches ChanOf, MapOf, and SliceOf lookups.
-var lookupCache struct {
- sync.RWMutex
- m map[cacheKey]*rtype
-}
-
-// A cacheKey is the key for use in the lookupCache.
-// Four values describe any of the types we are looking for:
-// type kind, one or two subtypes, and an extra integer.
-type cacheKey struct {
- kind Kind
- t1 *rtype
- t2 *rtype
- extra uintptr
-}
-
-// cacheGet looks for a type under the key k in the lookupCache.
-// If it finds one, it returns that type.
-// If not, it returns nil with the cache locked.
-// The caller is expected to use cachePut to unlock the cache.
-func cacheGet(k cacheKey) Type {
- lookupCache.RLock()
- t := lookupCache.m[k]
- lookupCache.RUnlock()
- if t != nil {
- return t
- }
-
- lookupCache.Lock()
- t = lookupCache.m[k]
- if t != nil {
- lookupCache.Unlock()
- return t
- }
-
- if lookupCache.m == nil {
- lookupCache.m = make(map[cacheKey]*rtype)
- }
-
- return nil
-}
-
-// cachePut stores the given type in the cache, unlocks the cache,
-// and returns the type. It is expected that the cache is locked
-// because cacheGet returned nil.
-func cachePut(k cacheKey, t *rtype) Type {
- lookupCache.m[k] = t
- lookupCache.Unlock()
- return t
-}
-
-// garbage collection bytecode program for chan.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type chanGC struct {
- width uintptr // sizeof(map)
- op uintptr // _GC_CHAN_PTR
- off uintptr // 0
- typ *rtype // map type
- end uintptr // _GC_END
-}
-
-type badGC struct {
- width uintptr
- end uintptr
-}
-
-// ChanOf returns the channel type with the given direction and element type.
-// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
-//
-// The gc runtime imposes a limit of 64 kB on channel element types.
-// If t's size is equal to or exceeds this limit, ChanOf panics.
-func ChanOf(dir ChanDir, t Type) Type {
- typ := t.(*rtype)
-
- // Look in cache.
- ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
- if ch := cacheGet(ckey); ch != nil {
- return ch
- }
-
- // This restriction is imposed by the gc compiler and the runtime.
- if typ.size >= 1<<16 {
- lookupCache.Unlock()
- panic("reflect.ChanOf: element size too large")
- }
-
- // Look in known types.
- // TODO: Precedence when constructing string.
- var s string
- switch dir {
- default:
- lookupCache.Unlock()
- panic("reflect.ChanOf: invalid dir")
- case SendDir:
- s = "chan<- " + *typ.string
- case RecvDir:
- s = "<-chan " + *typ.string
- case BothDir:
- s = "chan " + *typ.string
- }
- for _, tt := range typesByString(s) {
- ch := (*chanType)(unsafe.Pointer(tt))
- if ch.elem == typ && ch.dir == uintptr(dir) {
- return cachePut(ckey, tt)
- }
- }
-
- // Make a channel type.
- var ichan interface{} = (chan unsafe.Pointer)(nil)
- prototype := *(**chanType)(unsafe.Pointer(&ichan))
- ch := new(chanType)
- *ch = *prototype
- ch.string = &s
- ch.hash = fnv1(typ.hash, 'c', byte(dir))
- ch.elem = typ
- ch.uncommonType = nil
- ch.ptrToThis = nil
- ch.zero = unsafe.Pointer(&make([]byte, ch.size)[0])
-
- ch.gc = unsafe.Pointer(&chanGC{
- width: ch.size,
- op: _GC_CHAN_PTR,
- off: 0,
- typ: &ch.rtype,
- end: _GC_END,
- })
-
- // INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
- //ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
-
- return cachePut(ckey, &ch.rtype)
-}
-
-func ismapkey(*rtype) bool // implemented in runtime
-
-// MapOf returns the map type with the given key and element types.
-// For example, if k represents int and e represents string,
-// MapOf(k, e) represents map[int]string.
-//
-// If the key type is not a valid map key type (that is, if it does
-// not implement Go's == operator), MapOf panics.
-func MapOf(key, elem Type) Type {
- ktyp := key.(*rtype)
- etyp := elem.(*rtype)
-
- if !ismapkey(ktyp) {
- panic("reflect.MapOf: invalid key type " + ktyp.String())
- }
-
- // Look in cache.
- ckey := cacheKey{Map, ktyp, etyp, 0}
- if mt := cacheGet(ckey); mt != nil {
- return mt
- }
-
- // Look in known types.
- s := "map[" + *ktyp.string + "]" + *etyp.string
- for _, tt := range typesByString(s) {
- mt := (*mapType)(unsafe.Pointer(tt))
- if mt.key == ktyp && mt.elem == etyp {
- return cachePut(ckey, tt)
- }
- }
-
- // Make a map type.
- var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
- prototype := *(**mapType)(unsafe.Pointer(&imap))
- mt := new(mapType)
- *mt = *prototype
- mt.string = &s
- mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
- mt.key = ktyp
- mt.elem = etyp
- mt.bucket = bucketOf(ktyp, etyp)
- mt.hmap = hMapOf(mt.bucket)
- mt.uncommonType = nil
- mt.ptrToThis = nil
- mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0])
- mt.gc = unsafe.Pointer(&ptrGC{
- width: unsafe.Sizeof(uintptr(0)),
- op: _GC_PTR,
- off: 0,
- elemgc: mt.hmap.gc,
- end: _GC_END,
- })
-
- // INCORRECT. Uncomment to check that TestMapOfGC and TestMapOfGCValues
- // fail when mt.gc is wrong.
- //mt.gc = unsafe.Pointer(&badGC{width: mt.size, end: _GC_END})
-
- return cachePut(ckey, &mt.rtype)
-}
-
-// Make sure these routines stay in sync with ../../pkg/runtime/hashmap.c!
-// These types exist only for GC, so we only fill out GC relevant info.
-// Currently, that's just size and the GC program. We also fill in string
-// for possible debugging use.
-const (
- _BUCKETSIZE = 8
- _MAXKEYSIZE = 128
- _MAXVALSIZE = 128
-)
-
-func bucketOf(ktyp, etyp *rtype) *rtype {
- if ktyp.size > _MAXKEYSIZE {
- ktyp = PtrTo(ktyp).(*rtype)
- }
- if etyp.size > _MAXVALSIZE {
- etyp = PtrTo(etyp).(*rtype)
- }
- ptrsize := unsafe.Sizeof(uintptr(0))
-
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := _BUCKETSIZE * unsafe.Sizeof(uint8(0)) // topbits
- gc = append(gc, _GC_PTR, offset, 0 /*self pointer set below*/) // overflow
- offset += ptrsize
-
- if runtime.GOARCH == "amd64p32" {
- offset += 4
- }
-
- // keys
- if ktyp.kind&kindNoPointers == 0 {
- gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, ktyp.size)
- gc = appendGCProgram(gc, ktyp)
- gc = append(gc, _GC_ARRAY_NEXT)
- }
- offset += _BUCKETSIZE * ktyp.size
-
- // values
- if etyp.kind&kindNoPointers == 0 {
- gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, etyp.size)
- gc = appendGCProgram(gc, etyp)
- gc = append(gc, _GC_ARRAY_NEXT)
- }
- offset += _BUCKETSIZE * etyp.size
-
- gc = append(gc, _GC_END)
- gc[0] = offset
- gc[3] = uintptr(unsafe.Pointer(&gc[0])) // set self pointer
-
- b := new(rtype)
- b.size = offset
- b.gc = unsafe.Pointer(&gc[0])
- s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
- b.string = &s
- return b
-}
-
-// Take the GC program for "t" and append it to the GC program "gc".
-func appendGCProgram(gc []uintptr, t *rtype) []uintptr {
- p := t.gc
- p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
-loop:
- for {
- var argcnt int
- switch *(*uintptr)(p) {
- case _GC_END:
- // Note: _GC_END not included in append
- break loop
- case _GC_ARRAY_NEXT:
- argcnt = 0
- case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
- argcnt = 1
- case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
- argcnt = 2
- case _GC_ARRAY_START, _GC_REGION:
- argcnt = 3
- default:
- panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
- }
- for i := 0; i < argcnt+1; i++ {
- gc = append(gc, *(*uintptr)(p))
- p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
- }
- }
- return gc
-}
-func hMapOf(bucket *rtype) *rtype {
- ptrsize := unsafe.Sizeof(uintptr(0))
-
- // make gc program & compute hmap size
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := unsafe.Sizeof(uint(0)) // count
- offset += unsafe.Sizeof(uint32(0)) // flags
- offset += unsafe.Sizeof(uint32(0)) // hash0
- offset += unsafe.Sizeof(uint8(0)) // B
- offset += unsafe.Sizeof(uint8(0)) // keysize
- offset += unsafe.Sizeof(uint8(0)) // valuesize
- offset = (offset + 1) / 2 * 2
- offset += unsafe.Sizeof(uint16(0)) // bucketsize
- offset = (offset + ptrsize - 1) / ptrsize * ptrsize
- gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
- offset += ptrsize
- gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
- offset += ptrsize
- offset += ptrsize // nevacuate
- gc = append(gc, _GC_END)
- gc[0] = offset
-
- h := new(rtype)
- h.size = offset
- h.gc = unsafe.Pointer(&gc[0])
- s := "hmap(" + *bucket.string + ")"
- h.string = &s
- return h
-}
-
-// garbage collection bytecode program for slice of non-zero-length values.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type sliceGC struct {
- width uintptr // sizeof(slice)
- op uintptr // _GC_SLICE
- off uintptr // 0
- elemgc unsafe.Pointer // element gc program
- end uintptr // _GC_END
-}
-
-// garbage collection bytecode program for slice of zero-length values.
-// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type sliceEmptyGC struct {
- width uintptr // sizeof(slice)
- op uintptr // _GC_APTR
- off uintptr // 0
- end uintptr // _GC_END
-}
-
-var sliceEmptyGCProg = sliceEmptyGC{
- width: unsafe.Sizeof([]byte(nil)),
- op: _GC_APTR,
- off: 0,
- end: _GC_END,
-}
-
-// SliceOf returns the slice type with element type t.
-// For example, if t represents int, SliceOf(t) represents []int.
-func SliceOf(t Type) Type {
- typ := t.(*rtype)
-
- // Look in cache.
- ckey := cacheKey{Slice, typ, nil, 0}
- if slice := cacheGet(ckey); slice != nil {
- return slice
- }
-
- // Look in known types.
- s := "[]" + *typ.string
- for _, tt := range typesByString(s) {
- slice := (*sliceType)(unsafe.Pointer(tt))
- if slice.elem == typ {
- return cachePut(ckey, tt)
- }
- }
-
- // Make a slice type.
- var islice interface{} = ([]unsafe.Pointer)(nil)
- prototype := *(**sliceType)(unsafe.Pointer(&islice))
- slice := new(sliceType)
- *slice = *prototype
- slice.string = &s
- slice.hash = fnv1(typ.hash, '[')
- slice.elem = typ
- slice.uncommonType = nil
- slice.ptrToThis = nil
- slice.zero = unsafe.Pointer(&make([]byte, slice.size)[0])
-
- if typ.size == 0 {
- slice.gc = unsafe.Pointer(&sliceEmptyGCProg)
- } else {
- slice.gc = unsafe.Pointer(&sliceGC{
- width: slice.size,
- op: _GC_SLICE,
- off: 0,
- elemgc: typ.gc,
- end: _GC_END,
- })
- }
-
- // INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
- //slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
-
- return cachePut(ckey, &slice.rtype)
-}
-
-// ArrayOf returns the array type with the given count and element type.
-// For example, if t represents int, ArrayOf(5, t) represents [5]int.
-//
-// If the resulting type would be larger than the available address space,
-// ArrayOf panics.
-//
-// TODO(rsc): Unexported for now. Export once the alg field is set correctly
-// for the type. This may require significant work.
-func arrayOf(count int, elem Type) Type {
- typ := elem.(*rtype)
- slice := SliceOf(elem)
-
- // Look in cache.
- ckey := cacheKey{Array, typ, nil, uintptr(count)}
- if slice := cacheGet(ckey); slice != nil {
- return slice
- }
-
- // Look in known types.
- s := "[" + strconv.Itoa(count) + "]" + *typ.string
- for _, tt := range typesByString(s) {
- slice := (*sliceType)(unsafe.Pointer(tt))
- if slice.elem == typ {
- return cachePut(ckey, tt)
- }
- }
-
- // Make an array type.
- var iarray interface{} = [1]unsafe.Pointer{}
- prototype := *(**arrayType)(unsafe.Pointer(&iarray))
- array := new(arrayType)
- *array = *prototype
- array.string = &s
- array.hash = fnv1(typ.hash, '[')
- for n := uint32(count); n > 0; n >>= 8 {
- array.hash = fnv1(array.hash, byte(n))
- }
- array.hash = fnv1(array.hash, ']')
- array.elem = typ
- max := ^uintptr(0) / typ.size
- if uintptr(count) > max {
- panic("reflect.ArrayOf: array size would exceed virtual address space")
- }
- array.size = typ.size * uintptr(count)
- array.align = typ.align
- array.fieldAlign = typ.fieldAlign
- // TODO: array.alg
- // TODO: array.gc
- array.uncommonType = nil
- array.ptrToThis = nil
- array.zero = unsafe.Pointer(&make([]byte, array.size)[0])
- array.len = uintptr(count)
- array.slice = slice.(*rtype)
-
- return cachePut(ckey, &array.rtype)
-}
-
-// toType converts from a *rtype to a Type that can be returned
-// to the client of package reflect. In gc, the only concern is that
-// a nil *rtype must be replaced by a nil Type, but in gccgo this
-// function takes care of ensuring that multiple *rtype for the same
-// type are coalesced into a single Type.
-func toType(t *rtype) Type {
- if t == nil {
- return nil
- }
- return t
-}
-
-type layoutKey struct {
- t *rtype // function signature
- rcvr *rtype // receiver type, or nil if none
-}
-
-type layoutType struct {
- t *rtype
- argSize uintptr // size of arguments
- retOffset uintptr // offset of return values.
-}
-
-var layoutCache struct {
- sync.RWMutex
- m map[layoutKey]layoutType
-}
-
-// funcLayout computes a struct type representing the layout of the
-// function arguments and return values for the function type t.
-// If rcvr != nil, rcvr specifies the type of the receiver.
-// The returned type exists only for GC, so we only fill out GC relevant info.
-// Currently, that's just size and the GC program. We also fill in
-// the name for possible debugging use.
-func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr) {
- if t.Kind() != Func {
- panic("reflect: funcLayout of non-func type")
- }
- if rcvr != nil && rcvr.Kind() == Interface {
- panic("reflect: funcLayout with interface receiver " + rcvr.String())
- }
- k := layoutKey{t, rcvr}
- layoutCache.RLock()
- if x := layoutCache.m[k]; x.t != nil {
- layoutCache.RUnlock()
- return x.t, x.argSize, x.retOffset
- }
- layoutCache.RUnlock()
- layoutCache.Lock()
- if x := layoutCache.m[k]; x.t != nil {
- layoutCache.Unlock()
- return x.t, x.argSize, x.retOffset
- }
-
- tt := (*funcType)(unsafe.Pointer(t))
-
- // compute gc program for arguments
- gc := make([]uintptr, 1) // first entry is size, filled in at the end
- offset := uintptr(0)
- if rcvr != nil {
- // Reflect uses the "interface" calling convention for
- // methods, where receivers take one word of argument
- // space no matter how big they actually are.
- if rcvr.size > ptrSize {
- // we pass a pointer to the receiver.
- gc = append(gc, _GC_PTR, offset, uintptr(rcvr.gc))
- } else if rcvr.pointers() {
- // rcvr is a one-word pointer object. Its gc program
- // is just what we need here.
- gc = appendGCProgram(gc, rcvr)
- }
- offset += ptrSize
- }
- for _, arg := range tt.in {
- offset = align(offset, uintptr(arg.align))
- if arg.pointers() {
- gc = append(gc, _GC_REGION, offset, arg.size, uintptr(arg.gc))
- }
- offset += arg.size
- }
- argSize = offset
- if runtime.GOARCH == "amd64p32" {
- offset = align(offset, 8)
- }
- offset = align(offset, ptrSize)
- retOffset = offset
- for _, res := range tt.out {
- offset = align(offset, uintptr(res.align))
- if res.pointers() {
- gc = append(gc, _GC_REGION, offset, res.size, uintptr(res.gc))
- }
- offset += res.size
- }
- gc = append(gc, _GC_END)
- gc[0] = offset
-
- // build dummy rtype holding gc program
- x := new(rtype)
- x.size = offset
- x.gc = unsafe.Pointer(&gc[0])
- var s string
- if rcvr != nil {
- s = "methodargs(" + *rcvr.string + ")(" + *t.string + ")"
- } else {
- s = "funcargs(" + *t.string + ")"
- }
- x.string = &s
-
- // cache result for future callers
- if layoutCache.m == nil {
- layoutCache.m = make(map[layoutKey]layoutType)
- }
- layoutCache.m[k] = layoutType{
- t: x,
- argSize: argSize,
- retOffset: retOffset,
- }
- layoutCache.Unlock()
- return x, argSize, retOffset
-}
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
deleted file mode 100644
index 576cbc398..000000000
--- a/src/pkg/reflect/value.go
+++ /dev/null
@@ -1,2684 +0,0 @@
-// Copyright 2009 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
-
-import (
- "math"
- "runtime"
- "strconv"
- "unsafe"
-)
-
-const bigEndian = false // can be smarter if we find a big-endian machine
-const ptrSize = unsafe.Sizeof((*byte)(nil))
-const cannotSet = "cannot set value obtained from unexported struct field"
-
-// TODO: This will have to go away when
-// the new gc goes in.
-func memmove(adst, asrc unsafe.Pointer, n uintptr) {
- dst := uintptr(adst)
- src := uintptr(asrc)
- switch {
- case src < dst && src+n > dst:
- // byte copy backward
- // careful: i is unsigned
- for i := n; i > 0; {
- i--
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- case (n|src|dst)&(ptrSize-1) != 0:
- // byte copy forward
- for i := uintptr(0); i < n; i++ {
- *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
- }
- default:
- // word copy forward
- for i := uintptr(0); i < n; i += ptrSize {
- *(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
- }
- }
-}
-
-// Value is the reflection interface to a Go value.
-//
-// Not all methods apply to all kinds of values. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of value before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run time panic.
-//
-// The zero Value represents no value.
-// Its IsValid method returns false, its Kind method returns Invalid,
-// its String method returns "<invalid Value>", and all other methods panic.
-// Most functions and methods never return an invalid value.
-// If one does, its documentation states the conditions explicitly.
-//
-// A Value can be used concurrently by multiple goroutines provided that
-// the underlying Go value can be used concurrently for the equivalent
-// direct operations.
-type Value struct {
- // typ holds the type of the value represented by a Value.
- typ *rtype
-
- // Pointer-valued data or, if flagIndir is set, pointer to data.
- // Valid when either flagIndir is set or typ.pointers() is true.
- ptr unsafe.Pointer
-
- // Non-pointer-valued data. When the data is smaller
- // than a word, it begins at the first byte (in the memory
- // address sense) of this field.
- // Valid when flagIndir is not set and typ.pointers() is false.
- scalar uintptr
-
- // flag holds metadata about the value.
- // The lowest bits are flag bits:
- // - flagRO: obtained via unexported field, so read-only
- // - flagIndir: val holds a pointer to the data
- // - flagAddr: v.CanAddr is true (implies flagIndir)
- // - flagMethod: v is a method value.
- // The next five bits give the Kind of the value.
- // This repeats typ.Kind() except for method values.
- // The remaining 23+ bits give a method number for method values.
- // If flag.kind() != Func, code can assume that flagMethod is unset.
- // If typ.size > ptrSize, code can assume that flagIndir is set.
- flag
-
- // A method value represents a curried method invocation
- // like r.Read for some receiver r. The typ+val+flag bits describe
- // the receiver r, but the flag's Kind bits say Func (methods are
- // functions), and the top bits of the flag give the method number
- // in r's type's method table.
-}
-
-type flag uintptr
-
-const (
- flagRO flag = 1 << iota
- flagIndir
- flagAddr
- flagMethod
- flagKindShift = iota
- flagKindWidth = 5 // there are 27 kinds
- flagKindMask flag = 1<<flagKindWidth - 1
- flagMethodShift = flagKindShift + flagKindWidth
-)
-
-func (f flag) kind() Kind {
- return Kind((f >> flagKindShift) & flagKindMask)
-}
-
-// pointer returns the underlying pointer represented by v.
-// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer
-func (v Value) pointer() unsafe.Pointer {
- if v.typ.size != ptrSize || !v.typ.pointers() {
- panic("can't call pointer on a non-pointer Value")
- }
- if v.flag&flagIndir != 0 {
- return *(*unsafe.Pointer)(v.ptr)
- }
- return v.ptr
-}
-
-// packEface converts v to the empty interface.
-func packEface(v Value) interface{} {
- t := v.typ
- var i interface{}
- e := (*emptyInterface)(unsafe.Pointer(&i))
- // First, fill in the data portion of the interface.
- switch {
- case t.size > ptrSize:
- // Value is indirect, and so is the interface we're making.
- ptr := v.ptr
- if v.flag&flagAddr != 0 {
- // TODO: pass safe boolean from valueInterface so
- // we don't need to copy if safe==true?
- c := unsafe_New(t)
- memmove(c, ptr, t.size)
- ptr = c
- }
- e.word = iword(ptr)
- case v.flag&flagIndir != 0:
- // Value is indirect, but interface is direct. We need
- // to load the data at v.ptr into the interface data word.
- if t.pointers() {
- e.word = iword(*(*unsafe.Pointer)(v.ptr))
- } else {
- e.word = iword(loadScalar(v.ptr, t.size))
- }
- default:
- // Value is direct, and so is the interface.
- if t.pointers() {
- e.word = iword(v.ptr)
- } else {
- e.word = iword(v.scalar)
- }
- }
- // Now, fill in the type portion. We're very careful here not
- // to have any operation between the e.word and e.typ assignments
- // that would let the garbage collector observe the partially-built
- // interface value.
- e.typ = t
- return i
-}
-
-// unpackEface converts the empty interface i to a Value.
-func unpackEface(i interface{}) Value {
- e := (*emptyInterface)(unsafe.Pointer(&i))
- // NOTE: don't read e.word until we know whether it is really a pointer or not.
- t := e.typ
- if t == nil {
- return Value{}
- }
- f := flag(t.Kind()) << flagKindShift
- if t.size > ptrSize {
- return Value{t, unsafe.Pointer(e.word), 0, f | flagIndir}
- }
- if t.pointers() {
- return Value{t, unsafe.Pointer(e.word), 0, f}
- }
- return Value{t, nil, uintptr(e.word), f}
-}
-
-// A ValueError occurs when a Value method is invoked on
-// a Value that does not support it. Such cases are documented
-// in the description of each method.
-type ValueError struct {
- Method string
- Kind Kind
-}
-
-func (e *ValueError) Error() string {
- if e.Kind == 0 {
- return "reflect: call of " + e.Method + " on zero Value"
- }
- return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
-}
-
-// methodName returns the name of the calling method,
-// assumed to be two stack frames above.
-func methodName() string {
- pc, _, _, _ := runtime.Caller(2)
- f := runtime.FuncForPC(pc)
- if f == nil {
- return "unknown method"
- }
- return f.Name()
-}
-
-// An iword is the word that would be stored in an
-// interface to represent a given value v. Specifically, if v is
-// bigger than a pointer, its word is a pointer to v's data.
-// Otherwise, its word holds the data stored
-// in its leading bytes (so is not a pointer).
-// This type is very dangerous for the garbage collector because
-// it must be treated conservatively. We try to never expose it
-// to the GC here so that GC remains precise.
-type iword unsafe.Pointer
-
-// loadScalar loads n bytes at p from memory into a uintptr
-// that forms the second word of an interface. The data
-// must be non-pointer in nature.
-func loadScalar(p unsafe.Pointer, n uintptr) uintptr {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- var w uintptr
- switch n {
- default:
- panic("reflect: internal error: loadScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
- case 2:
- *(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
- case 3:
- *(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
- case 4:
- *(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
- case 5:
- *(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
- case 6:
- *(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
- case 7:
- *(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
- case 8:
- *(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
- }
- return w
-}
-
-// storeScalar stores n bytes from w into p.
-func storeScalar(p unsafe.Pointer, w uintptr, n uintptr) {
- // Run the copy ourselves instead of calling memmove
- // to avoid moving w to the heap.
- switch n {
- default:
- panic("reflect: internal error: storeScalar of " + strconv.Itoa(int(n)) + "-byte value")
- case 0:
- case 1:
- *(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
- case 2:
- *(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
- case 3:
- *(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
- case 4:
- *(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
- case 5:
- *(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
- case 6:
- *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
- case 7:
- *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
- case 8:
- *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
- }
-}
-
-// emptyInterface is the header for an interface{} value.
-type emptyInterface struct {
- typ *rtype
- word iword
-}
-
-// nonEmptyInterface is the header for a interface value with methods.
-type nonEmptyInterface struct {
- // see ../runtime/iface.c:/Itab
- itab *struct {
- ityp *rtype // static interface type
- typ *rtype // dynamic concrete type
- link unsafe.Pointer
- bad int32
- unused int32
- fun [100000]unsafe.Pointer // method table
- }
- word iword
-}
-
-// mustBe panics if f's kind is not expected.
-// Making this a method on flag instead of on Value
-// (and embedding flag in Value) means that we can write
-// the very clear v.mustBe(Bool) and have it compile into
-// v.flag.mustBe(Bool), which will only bother to copy the
-// single important word for the receiver.
-func (f flag) mustBe(expected Kind) {
- k := f.kind()
- if k != expected {
- panic(&ValueError{methodName(), k})
- }
-}
-
-// mustBeExported panics if f records that the value was obtained using
-// an unexported field.
-func (f flag) mustBeExported() {
- if f == 0 {
- panic(&ValueError{methodName(), 0})
- }
- if f&flagRO != 0 {
- panic("reflect: " + methodName() + " using value obtained using unexported field")
- }
-}
-
-// mustBeAssignable panics if f records that the value is not assignable,
-// which is to say that either it was obtained using an unexported field
-// or it is not addressable.
-func (f flag) mustBeAssignable() {
- if f == 0 {
- panic(&ValueError{methodName(), Invalid})
- }
- // Assignable if addressable and not read-only.
- if f&flagRO != 0 {
- panic("reflect: " + methodName() + " using value obtained using unexported field")
- }
- if f&flagAddr == 0 {
- panic("reflect: " + methodName() + " using unaddressable value")
- }
-}
-
-// Addr returns a pointer value representing the address of v.
-// It panics if CanAddr() returns false.
-// Addr is typically used to obtain a pointer to a struct field
-// or slice element in order to call a method that requires a
-// pointer receiver.
-func (v Value) Addr() Value {
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Addr of unaddressable value")
- }
- return Value{v.typ.ptrTo(), v.ptr, 0, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
-}
-
-// Bool returns v's underlying value.
-// It panics if v's kind is not Bool.
-func (v Value) Bool() bool {
- v.mustBe(Bool)
- if v.flag&flagIndir != 0 {
- return *(*bool)(v.ptr)
- }
- return *(*bool)(unsafe.Pointer(&v.scalar))
-}
-
-// Bytes returns v's underlying value.
-// It panics if v's underlying value is not a slice of bytes.
-func (v Value) Bytes() []byte {
- v.mustBe(Slice)
- if v.typ.Elem().Kind() != Uint8 {
- panic("reflect.Value.Bytes of non-byte slice")
- }
- // Slice is always bigger than a word; assume flagIndir.
- return *(*[]byte)(v.ptr)
-}
-
-// 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.ptr)
-}
-
-// 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
-// an element of a slice, an element of an addressable array,
-// a field of an addressable struct, or the result of dereferencing a pointer.
-// If CanAddr returns false, calling Addr will panic.
-func (v Value) CanAddr() bool {
- return v.flag&flagAddr != 0
-}
-
-// CanSet returns true if the value of v can be changed.
-// A Value can be changed only if it is addressable and was not
-// obtained by the use of unexported struct fields.
-// If CanSet returns false, calling Set or any type-specific
-// setter (e.g., SetBool, SetInt64) will panic.
-func (v Value) CanSet() bool {
- return v.flag&(flagAddr|flagRO) == flagAddr
-}
-
-// Call calls the function v with the input arguments in.
-// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
-// Call panics if v's Kind is not Func.
-// It returns the output results as Values.
-// As in Go, each input argument must be assignable to the
-// type of the function's corresponding input parameter.
-// If v is a variadic function, Call creates the variadic slice parameter
-// itself, copying in the corresponding values.
-func (v Value) Call(in []Value) []Value {
- v.mustBe(Func)
- v.mustBeExported()
- return v.call("Call", in)
-}
-
-// CallSlice calls the variadic function v with the input arguments in,
-// assigning the slice in[len(in)-1] to v's final variadic argument.
-// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...).
-// Call panics if v's Kind is not Func or if v is not variadic.
-// It returns the output results as Values.
-// As in Go, each input argument must be assignable to the
-// type of the function's corresponding input parameter.
-func (v Value) CallSlice(in []Value) []Value {
- v.mustBe(Func)
- v.mustBeExported()
- return v.call("CallSlice", in)
-}
-
-var callGC bool // for testing; see TestCallMethodJump
-
-var makeFuncStubFn = makeFuncStub
-var makeFuncStubCode = **(**uintptr)(unsafe.Pointer(&makeFuncStubFn))
-var methodValueCallFn = methodValueCall
-var methodValueCallCode = **(**uintptr)(unsafe.Pointer(&methodValueCallFn))
-
-func (v Value) call(op string, in []Value) []Value {
- // Get function pointer, type.
- t := v.typ
- var (
- fn unsafe.Pointer
- rcvr Value
- rcvrtype *rtype
- )
- if v.flag&flagMethod != 0 {
- rcvr = v
- rcvrtype, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
- } else if v.flag&flagIndir != 0 {
- fn = *(*unsafe.Pointer)(v.ptr)
- } else {
- fn = v.ptr
- }
-
- if fn == nil {
- panic("reflect.Value.Call: call of nil function")
- }
-
- isSlice := op == "CallSlice"
- n := t.NumIn()
- if isSlice {
- if !t.IsVariadic() {
- panic("reflect: CallSlice of non-variadic function")
- }
- if len(in) < n {
- panic("reflect: CallSlice with too few input arguments")
- }
- if len(in) > n {
- panic("reflect: CallSlice with too many input arguments")
- }
- } else {
- if t.IsVariadic() {
- n--
- }
- if len(in) < n {
- panic("reflect: Call with too few input arguments")
- }
- if !t.IsVariadic() && len(in) > n {
- panic("reflect: Call with too many input arguments")
- }
- }
- for _, x := range in {
- if x.Kind() == Invalid {
- panic("reflect: " + op + " using zero Value argument")
- }
- }
- for i := 0; i < n; i++ {
- if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
- panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
- }
- }
- if !isSlice && t.IsVariadic() {
- // prepare slice for remaining values
- m := len(in) - n
- slice := MakeSlice(t.In(n), m, m)
- elem := t.In(n).Elem()
- for i := 0; i < m; i++ {
- x := in[n+i]
- if xt := x.Type(); !xt.AssignableTo(elem) {
- panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
- }
- slice.Index(i).Set(x)
- }
- origIn := in
- in = make([]Value, n+1)
- copy(in[:n], origIn)
- in[n] = slice
- }
-
- nin := len(in)
- if nin != t.NumIn() {
- panic("reflect.Value.Call: wrong argument count")
- }
- nout := t.NumOut()
-
- // If target is makeFuncStub, short circuit the unpack onto stack /
- // pack back into []Value for the args and return values. Just do the
- // call directly.
- // We need to do this here because otherwise we have a situation where
- // reflect.callXX calls makeFuncStub, neither of which knows the
- // layout of the args. That's bad for precise gc & stack copying.
- x := (*makeFuncImpl)(fn)
- if x.code == makeFuncStubCode {
- return x.fn(in)
- }
-
- // If the target is methodValueCall, do its work here: add the receiver
- // argument and call the real target directly.
- // We need to do this here because otherwise we have a situation where
- // reflect.callXX calls methodValueCall, neither of which knows the
- // layout of the args. That's bad for precise gc & stack copying.
- y := (*methodValue)(fn)
- if y.fn == methodValueCallCode {
- rcvr = y.rcvr
- rcvrtype, t, fn = methodReceiver("call", rcvr, y.method)
- }
-
- // Compute frame type, allocate a chunk of memory for frame
- frametype, _, retOffset := funcLayout(t, rcvrtype)
- args := unsafe_New(frametype)
- off := uintptr(0)
-
- // Copy inputs into args.
- if rcvrtype != nil {
- storeRcvr(rcvr, args)
- off = ptrSize
- }
- for i, v := range in {
- v.mustBeExported()
- targ := t.In(i).(*rtype)
- a := uintptr(targ.align)
- off = (off + a - 1) &^ (a - 1)
- n := targ.size
- addr := unsafe.Pointer(uintptr(args) + off)
- v = v.assignTo("reflect.Value.Call", targ, (*interface{})(addr))
- if v.flag&flagIndir != 0 {
- memmove(addr, v.ptr, n)
- } else if targ.pointers() {
- *(*unsafe.Pointer)(addr) = v.ptr
- } else {
- storeScalar(addr, v.scalar, n)
- }
- off += n
- }
-
- // Call.
- call(fn, args, uint32(frametype.size), uint32(retOffset))
-
- // For testing; see TestCallMethodJump.
- if callGC {
- runtime.GC()
- }
-
- // Copy return values out of args.
- ret := make([]Value, nout)
- off = retOffset
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- a := uintptr(tv.Align())
- off = (off + a - 1) &^ (a - 1)
- fl := flagIndir | flag(tv.Kind())<<flagKindShift
- ret[i] = Value{tv.common(), unsafe.Pointer(uintptr(args) + off), 0, fl}
- off += tv.Size()
- }
-
- return ret
-}
-
-// callReflect is the call implementation used by a function
-// returned by MakeFunc. In many ways it is the opposite of the
-// method Value.call above. The method above converts a call using Values
-// into a call of a function with a concrete argument frame, while
-// callReflect converts a call of a function with a concrete argument
-// frame into a call using Values.
-// It is in this file so that it can be next to the call method above.
-// The remainder of the MakeFunc implementation is in makefunc.go.
-//
-// NOTE: This function must be marked as a "wrapper" in the generated code,
-// so that the linker can make it work correctly for panic and recover.
-// The gc compilers know to do that for the name "reflect.callReflect".
-func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
- ftyp := ctxt.typ
- f := ctxt.fn
-
- // Copy argument frame into Values.
- ptr := frame
- off := uintptr(0)
- in := make([]Value, 0, len(ftyp.in))
- for _, arg := range ftyp.in {
- typ := arg
- off += -off & uintptr(typ.align-1)
- addr := unsafe.Pointer(uintptr(ptr) + off)
- v := Value{typ, nil, 0, flag(typ.Kind()) << flagKindShift}
- if typ.size > ptrSize {
- // value does not fit in word.
- // Must make a copy, because f might keep a reference to it,
- // and we cannot let f keep a reference to the stack frame
- // after this function returns, not even a read-only reference.
- v.ptr = unsafe_New(typ)
- memmove(v.ptr, addr, typ.size)
- v.flag |= flagIndir
- } else if typ.pointers() {
- v.ptr = *(*unsafe.Pointer)(addr)
- } else {
- v.scalar = loadScalar(addr, typ.size)
- }
- in = append(in, v)
- off += typ.size
- }
-
- // Call underlying function.
- out := f(in)
- if len(out) != len(ftyp.out) {
- panic("reflect: wrong return count from function created by MakeFunc")
- }
-
- // Copy results back into argument frame.
- if len(ftyp.out) > 0 {
- off += -off & (ptrSize - 1)
- if runtime.GOARCH == "amd64p32" {
- off = align(off, 8)
- }
- for i, arg := range ftyp.out {
- typ := arg
- v := out[i]
- if v.typ != typ {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned wrong type: have " +
- out[i].typ.String() + " for " + typ.String())
- }
- if v.flag&flagRO != 0 {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned value obtained from unexported field")
- }
- off += -off & uintptr(typ.align-1)
- addr := unsafe.Pointer(uintptr(ptr) + off)
- if v.flag&flagIndir != 0 {
- memmove(addr, v.ptr, typ.size)
- } else if typ.pointers() {
- *(*unsafe.Pointer)(addr) = v.ptr
- } else {
- storeScalar(addr, v.scalar, typ.size)
- }
- off += typ.size
- }
- }
-}
-
-// methodReceiver returns information about the receiver
-// described by v. The Value v may or may not have the
-// flagMethod bit set, so the kind cached in v.flag should
-// not be used.
-// The return value rcvrtype gives the method's actual receiver type.
-// The return value t gives the method type signature (without the receiver).
-// The return value fn is a pointer to the method code.
-func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
- i := methodIndex
- if v.typ.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
- panic("reflect: internal error: invalid method index")
- }
- m := &tt.methods[i]
- if m.pkgPath != nil {
- panic("reflect: " + op + " of unexported method")
- }
- iface := (*nonEmptyInterface)(v.ptr)
- if iface.itab == nil {
- panic("reflect: " + op + " of method on nil interface value")
- }
- rcvrtype = iface.itab.typ
- fn = unsafe.Pointer(&iface.itab.fun[i])
- t = m.typ
- } else {
- rcvrtype = v.typ
- ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
- panic("reflect: internal error: invalid method index")
- }
- m := &ut.methods[i]
- if m.pkgPath != nil {
- panic("reflect: " + op + " of unexported method")
- }
- fn = unsafe.Pointer(&m.ifn)
- t = m.mtyp
- }
- return
-}
-
-// v is a method receiver. Store at p the word which is used to
-// encode that receiver at the start of the argument list.
-// Reflect uses the "interface" calling convention for
-// methods, which always uses one word to record the receiver.
-func storeRcvr(v Value, p unsafe.Pointer) {
- t := v.typ
- if t.Kind() == Interface {
- // the interface data word becomes the receiver word
- iface := (*nonEmptyInterface)(v.ptr)
- *(*unsafe.Pointer)(p) = unsafe.Pointer(iface.word)
- } else if v.flag&flagIndir != 0 {
- if t.size > ptrSize {
- *(*unsafe.Pointer)(p) = v.ptr
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
- } else {
- *(*uintptr)(p) = loadScalar(v.ptr, t.size)
- }
- } else if t.pointers() {
- *(*unsafe.Pointer)(p) = v.ptr
- } else {
- *(*uintptr)(p) = v.scalar
- }
-}
-
-// align returns the result of rounding x up to a multiple of n.
-// n must be a power of two.
-func align(x, n uintptr) uintptr {
- return (x + n - 1) &^ (n - 1)
-}
-
-// callMethod is the call implementation used by a function returned
-// by makeMethodValue (used by v.Method(i).Interface()).
-// It is a streamlined version of the usual reflect call: the caller has
-// already laid out the argument frame for us, so we don't have
-// to deal with individual Values for each argument.
-// It is in this file so that it can be next to the two similar functions above.
-// The remainder of the makeMethodValue implementation is in makefunc.go.
-//
-// NOTE: This function must be marked as a "wrapper" in the generated code,
-// so that the linker can make it work correctly for panic and recover.
-// The gc compilers know to do that for the name "reflect.callMethod".
-func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
- rcvr := ctxt.rcvr
- rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
- frametype, argSize, retOffset := funcLayout(t, rcvrtype)
-
- // Make a new frame that is one word bigger so we can store the receiver.
- args := unsafe_New(frametype)
-
- // Copy in receiver and rest of args.
- storeRcvr(rcvr, args)
- memmove(unsafe.Pointer(uintptr(args)+ptrSize), frame, argSize-ptrSize)
-
- // Call.
- call(fn, args, uint32(frametype.size), uint32(retOffset))
-
- // Copy return values. On amd64p32, the beginning of return values
- // is 64-bit aligned, so the caller's frame layout (which doesn't have
- // a receiver) is different from the layout of the fn call, which has
- // a receiver.
- // Ignore any changes to args and just copy return values.
- callerRetOffset := retOffset - ptrSize
- if runtime.GOARCH == "amd64p32" {
- callerRetOffset = align(argSize-ptrSize, 8)
- }
- memmove(unsafe.Pointer(uintptr(frame)+callerRetOffset),
- unsafe.Pointer(uintptr(args)+retOffset), frametype.size-retOffset)
-}
-
-// funcName returns the name of f, for use in error messages.
-func funcName(f func([]Value) []Value) string {
- pc := *(*uintptr)(unsafe.Pointer(&f))
- rf := runtime.FuncForPC(pc)
- if rf != nil {
- return rf.Name()
- }
- return "closure"
-}
-
-// Cap returns v's capacity.
-// It panics if v's Kind is not Array, Chan, or Slice.
-func (v Value) Cap() int {
- k := v.kind()
- switch k {
- case Array:
- return v.typ.Len()
- case Chan:
- return int(chancap(v.pointer()))
- case Slice:
- // Slice is always bigger than a word; assume flagIndir.
- return (*sliceHeader)(v.ptr).Cap
- }
- panic(&ValueError{"reflect.Value.Cap", k})
-}
-
-// Close closes the channel v.
-// It panics if v's Kind is not Chan.
-func (v Value) Close() {
- v.mustBe(Chan)
- v.mustBeExported()
- chanclose(v.pointer())
-}
-
-// Complex returns v's underlying value, as a complex128.
-// It panics if v's Kind is not Complex64 or Complex128
-func (v Value) Complex() complex128 {
- k := v.kind()
- switch k {
- case Complex64:
- if v.flag&flagIndir != 0 {
- return complex128(*(*complex64)(v.ptr))
- }
- return complex128(*(*complex64)(unsafe.Pointer(&v.scalar)))
- case Complex128:
- // complex128 is always bigger than a word; assume flagIndir.
- return *(*complex128)(v.ptr)
- }
- panic(&ValueError{"reflect.Value.Complex", k})
-}
-
-// Elem returns the value that the interface v contains
-// or that the pointer v points to.
-// It panics if v's Kind is not Interface or Ptr.
-// It returns the zero Value if v is nil.
-func (v Value) Elem() Value {
- k := v.kind()
- switch k {
- case Interface:
- var eface interface{}
- if v.typ.NumMethod() == 0 {
- eface = *(*interface{})(v.ptr)
- } else {
- eface = (interface{})(*(*interface {
- M()
- })(v.ptr))
- }
- x := unpackEface(eface)
- x.flag |= v.flag & flagRO
- return x
- case Ptr:
- ptr := v.ptr
- if v.flag&flagIndir != 0 {
- ptr = *(*unsafe.Pointer)(ptr)
- }
- // The returned value's address is v's value.
- if ptr == nil {
- return Value{}
- }
- tt := (*ptrType)(unsafe.Pointer(v.typ))
- typ := tt.elem
- fl := v.flag&flagRO | flagIndir | flagAddr
- fl |= flag(typ.Kind() << flagKindShift)
- return Value{typ, ptr, 0, fl}
- }
- panic(&ValueError{"reflect.Value.Elem", k})
-}
-
-// Field returns the i'th field of the struct v.
-// It panics if v's Kind is not Struct or i is out of range.
-func (v Value) Field(i int) Value {
- v.mustBe(Struct)
- tt := (*structType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.fields) {
- panic("reflect: Field index out of range")
- }
- field := &tt.fields[i]
- typ := field.typ
-
- // Inherit permission bits from v.
- fl := v.flag & (flagRO | flagIndir | flagAddr)
- // Using an unexported field forces flagRO.
- if field.pkgPath != nil {
- fl |= flagRO
- }
- fl |= flag(typ.Kind()) << flagKindShift
-
- var ptr unsafe.Pointer
- var scalar uintptr
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- ptr = unsafe.Pointer(uintptr(v.ptr) + field.offset)
- case typ.pointers():
- if field.offset != 0 {
- panic("field access of ptr value isn't at offset 0")
- }
- ptr = v.ptr
- case bigEndian:
- // Must be scalar. Discard leading bytes.
- scalar = v.scalar << (field.offset * 8)
- default:
- // Must be scalar. Discard leading bytes.
- scalar = v.scalar >> (field.offset * 8)
- }
-
- return Value{typ, ptr, scalar, fl}
-}
-
-// FieldByIndex returns the nested field corresponding to index.
-// It panics if v's Kind is not struct.
-func (v Value) FieldByIndex(index []int) Value {
- v.mustBe(Struct)
- for i, x := range index {
- if i > 0 {
- if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct {
- if v.IsNil() {
- panic("reflect: indirection through nil pointer to embedded struct")
- }
- v = v.Elem()
- }
- }
- v = v.Field(x)
- }
- return v
-}
-
-// FieldByName returns the struct field with the given name.
-// It returns the zero Value if no field was found.
-// It panics if v's Kind is not struct.
-func (v Value) FieldByName(name string) Value {
- v.mustBe(Struct)
- if f, ok := v.typ.FieldByName(name); ok {
- return v.FieldByIndex(f.Index)
- }
- return Value{}
-}
-
-// FieldByNameFunc returns the struct field with a name
-// that satisfies the match function.
-// It panics if v's Kind is not struct.
-// It returns the zero Value if no field was found.
-func (v Value) FieldByNameFunc(match func(string) bool) Value {
- v.mustBe(Struct)
- if f, ok := v.typ.FieldByNameFunc(match); ok {
- return v.FieldByIndex(f.Index)
- }
- return Value{}
-}
-
-// Float returns v's underlying value, as a float64.
-// It panics if v's Kind is not Float32 or Float64
-func (v Value) Float() float64 {
- k := v.kind()
- switch k {
- case Float32:
- if v.flag&flagIndir != 0 {
- return float64(*(*float32)(v.ptr))
- }
- return float64(*(*float32)(unsafe.Pointer(&v.scalar)))
- case Float64:
- if v.flag&flagIndir != 0 {
- return *(*float64)(v.ptr)
- }
- return *(*float64)(unsafe.Pointer(&v.scalar))
- }
- panic(&ValueError{"reflect.Value.Float", k})
-}
-
-var uint8Type = TypeOf(uint8(0)).(*rtype)
-
-// Index returns v's i'th element.
-// It panics if v's Kind is not Array, Slice, or String or i is out of range.
-func (v Value) Index(i int) Value {
- k := v.kind()
- switch k {
- case Array:
- tt := (*arrayType)(unsafe.Pointer(v.typ))
- if i < 0 || i > int(tt.len) {
- panic("reflect: array index out of range")
- }
- typ := tt.elem
- fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
- fl |= flag(typ.Kind()) << flagKindShift
- offset := uintptr(i) * typ.size
-
- var val unsafe.Pointer
- var scalar uintptr
- switch {
- case fl&flagIndir != 0:
- // Indirect. Just bump pointer.
- val = unsafe.Pointer(uintptr(v.ptr) + offset)
- case typ.pointers():
- if offset != 0 {
- panic("can't Index(i) with i!=0 on ptrLike value")
- }
- val = v.ptr
- case bigEndian:
- // Direct. Discard leading bytes.
- scalar = v.scalar << (offset * 8)
- default:
- // Direct. Discard leading bytes.
- scalar = v.scalar >> (offset * 8)
- }
- return Value{typ, val, scalar, fl}
-
- case Slice:
- // Element flag same as Elem of Ptr.
- // Addressable, indirect, possibly read-only.
- fl := flagAddr | flagIndir | v.flag&flagRO
- s := (*sliceHeader)(v.ptr)
- if i < 0 || i >= s.Len {
- panic("reflect: slice index out of range")
- }
- tt := (*sliceType)(unsafe.Pointer(v.typ))
- typ := tt.elem
- fl |= flag(typ.Kind()) << flagKindShift
- val := unsafe.Pointer(uintptr(s.Data) + uintptr(i)*typ.size)
- return Value{typ, val, 0, fl}
-
- case String:
- fl := v.flag&flagRO | flag(Uint8<<flagKindShift)
- s := (*stringHeader)(v.ptr)
- if i < 0 || i >= s.Len {
- panic("reflect: string index out of range")
- }
- b := uintptr(0)
- *(*byte)(unsafe.Pointer(&b)) = *(*byte)(unsafe.Pointer(uintptr(s.Data) + uintptr(i)))
- return Value{uint8Type, nil, b, fl}
- }
- panic(&ValueError{"reflect.Value.Index", k})
-}
-
-// Int returns v's underlying value, as an int64.
-// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
-func (v Value) Int() int64 {
- k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- p = unsafe.Pointer(&v.scalar)
- }
- switch k {
- case Int:
- return int64(*(*int)(p))
- case Int8:
- return int64(*(*int8)(p))
- case Int16:
- return int64(*(*int16)(p))
- case Int32:
- return int64(*(*int32)(p))
- case Int64:
- return int64(*(*int64)(p))
- }
- panic(&ValueError{"reflect.Value.Int", k})
-}
-
-// CanInterface returns true if Interface can be used without panicking.
-func (v Value) CanInterface() bool {
- if v.flag == 0 {
- panic(&ValueError{"reflect.Value.CanInterface", Invalid})
- }
- return v.flag&flagRO == 0
-}
-
-// Interface returns v's current value as an interface{}.
-// It is equivalent to:
-// var i interface{} = (v's underlying value)
-// It panics if the Value was obtained by accessing
-// unexported struct fields.
-func (v Value) Interface() (i interface{}) {
- return valueInterface(v, true)
-}
-
-func valueInterface(v Value, safe bool) interface{} {
- if v.flag == 0 {
- panic(&ValueError{"reflect.Value.Interface", 0})
- }
- if safe && v.flag&flagRO != 0 {
- // Do not allow access to unexported values via Interface,
- // because they might be pointers that should not be
- // writable or methods or function that should not be callable.
- panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
- }
- if v.flag&flagMethod != 0 {
- v = makeMethodValue("Interface", v)
- }
-
- if v.kind() == Interface {
- // Special case: return the element inside the interface.
- // Empty interface has one layout, all interfaces with
- // methods have a second layout.
- if v.NumMethod() == 0 {
- return *(*interface{})(v.ptr)
- }
- return *(*interface {
- M()
- })(v.ptr)
- }
-
- // TODO: pass safe to packEface so we don't need to copy if safe==true?
- return packEface(v)
-}
-
-// InterfaceData returns the interface v's value as a uintptr pair.
-// It panics if v's Kind is not Interface.
-func (v Value) InterfaceData() [2]uintptr {
- // TODO: deprecate this
- v.mustBe(Interface)
- // We treat this as a read operation, so we allow
- // it even for unexported data, because the caller
- // has to import "unsafe" to turn it into something
- // that can be abused.
- // Interface value is always bigger than a word; assume flagIndir.
- return *(*[2]uintptr)(v.ptr)
-}
-
-// IsNil reports whether its argument v is nil. The argument must be
-// a chan, func, interface, map, pointer, or slice value; if it is
-// not, IsNil panics. Note that IsNil is not always equivalent to a
-// regular comparison with nil in Go. For example, if v was created
-// by calling ValueOf with an uninitialized interface variable i,
-// i==nil will be true but v.IsNil will panic as v will be the zero
-// Value.
-func (v Value) IsNil() bool {
- k := v.kind()
- switch k {
- case Chan, Func, Map, Ptr:
- if v.flag&flagMethod != 0 {
- return false
- }
- ptr := v.ptr
- if v.flag&flagIndir != 0 {
- ptr = *(*unsafe.Pointer)(ptr)
- }
- return ptr == nil
- case Interface, Slice:
- // Both interface and slice are nil if first word is 0.
- // Both are always bigger than a word; assume flagIndir.
- return *(*unsafe.Pointer)(v.ptr) == nil
- }
- panic(&ValueError{"reflect.Value.IsNil", k})
-}
-
-// IsValid returns true if v represents a value.
-// It returns false if v is the zero Value.
-// If IsValid returns false, all other methods except String panic.
-// Most functions and methods never return an invalid value.
-// If one does, its documentation states the conditions explicitly.
-func (v Value) IsValid() bool {
- return v.flag != 0
-}
-
-// Kind returns v's Kind.
-// If v is the zero Value (IsValid returns false), Kind returns Invalid.
-func (v Value) Kind() Kind {
- return v.kind()
-}
-
-// Len returns v's length.
-// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
-func (v Value) Len() int {
- k := v.kind()
- switch k {
- case Array:
- tt := (*arrayType)(unsafe.Pointer(v.typ))
- return int(tt.len)
- case Chan:
- return chanlen(v.pointer())
- case Map:
- return maplen(v.pointer())
- case Slice:
- // Slice is bigger than a word; assume flagIndir.
- return (*sliceHeader)(v.ptr).Len
- case String:
- // String is bigger than a word; assume flagIndir.
- return (*stringHeader)(v.ptr).Len
- }
- panic(&ValueError{"reflect.Value.Len", k})
-}
-
-// MapIndex returns the value associated with key in the map v.
-// It panics if v's Kind is not Map.
-// It returns the zero Value if key is not found in the map or if v represents a nil map.
-// As in Go, the key's value must be assignable to the map's key type.
-func (v Value) MapIndex(key Value) Value {
- v.mustBe(Map)
- tt := (*mapType)(unsafe.Pointer(v.typ))
-
- // Do not require key to be exported, so that DeepEqual
- // and other programs can use all the keys returned by
- // MapKeys as arguments to MapIndex. If either the map
- // or the key is unexported, though, the result will be
- // considered unexported. This is consistent with the
- // behavior for structs, which allow read but not write
- // of unexported fields.
- key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
-
- var k unsafe.Pointer
- if key.flag&flagIndir != 0 {
- k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
- } else {
- k = unsafe.Pointer(&key.scalar)
- }
- e := mapaccess(v.typ, v.pointer(), k)
- if e == nil {
- return Value{}
- }
- typ := tt.elem
- fl := (v.flag | key.flag) & flagRO
- fl |= flag(typ.Kind()) << flagKindShift
- if typ.size > ptrSize {
- // Copy result so future changes to the map
- // won't change the underlying value.
- c := unsafe_New(typ)
- memmove(c, e, typ.size)
- return Value{typ, c, 0, fl | flagIndir}
- } else if typ.pointers() {
- return Value{typ, *(*unsafe.Pointer)(e), 0, fl}
- } else {
- return Value{typ, nil, loadScalar(e, typ.size), fl}
- }
-}
-
-// MapKeys returns a slice containing all the keys present in the map,
-// in unspecified order.
-// It panics if v's Kind is not Map.
-// It returns an empty slice if v represents a nil map.
-func (v Value) MapKeys() []Value {
- v.mustBe(Map)
- tt := (*mapType)(unsafe.Pointer(v.typ))
- keyType := tt.key
-
- fl := v.flag&flagRO | flag(keyType.Kind())<<flagKindShift
-
- m := v.pointer()
- mlen := int(0)
- if m != nil {
- mlen = maplen(m)
- }
- it := mapiterinit(v.typ, m)
- a := make([]Value, mlen)
- var i int
- for i = 0; i < len(a); i++ {
- key := mapiterkey(it)
- if key == nil {
- // Someone deleted an entry from the map since we
- // called maplen above. It's a data race, but nothing
- // we can do about it.
- break
- }
- if keyType.size > ptrSize {
- // Copy result so future changes to the map
- // won't change the underlying value.
- c := unsafe_New(keyType)
- memmove(c, key, keyType.size)
- a[i] = Value{keyType, c, 0, fl | flagIndir}
- } else if keyType.pointers() {
- a[i] = Value{keyType, *(*unsafe.Pointer)(key), 0, fl}
- } else {
- a[i] = Value{keyType, nil, loadScalar(key, keyType.size), fl}
- }
- mapiternext(it)
- }
- return a[:i]
-}
-
-// Method returns a function value corresponding to v's i'th method.
-// The arguments to a Call on the returned function should not include
-// a receiver; the returned function will always use v as the receiver.
-// Method panics if i is out of range or if v is a nil interface value.
-func (v Value) Method(i int) Value {
- if v.typ == nil {
- panic(&ValueError{"reflect.Value.Method", Invalid})
- }
- if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
- panic("reflect: Method index out of range")
- }
- if v.typ.Kind() == Interface && v.IsNil() {
- panic("reflect: Method on nil interface value")
- }
- fl := v.flag & (flagRO | flagIndir)
- fl |= flag(Func) << flagKindShift
- fl |= flag(i)<<flagMethodShift | flagMethod
- return Value{v.typ, v.ptr, v.scalar, fl}
-}
-
-// NumMethod returns the number of methods in the value's method set.
-func (v Value) NumMethod() int {
- if v.typ == nil {
- panic(&ValueError{"reflect.Value.NumMethod", Invalid})
- }
- if v.flag&flagMethod != 0 {
- return 0
- }
- return v.typ.NumMethod()
-}
-
-// MethodByName returns a function value corresponding to the method
-// of v with the given name.
-// The arguments to a Call on the returned function should not include
-// a receiver; the returned function will always use v as the receiver.
-// It returns the zero Value if no method was found.
-func (v Value) MethodByName(name string) Value {
- if v.typ == nil {
- panic(&ValueError{"reflect.Value.MethodByName", Invalid})
- }
- if v.flag&flagMethod != 0 {
- return Value{}
- }
- m, ok := v.typ.MethodByName(name)
- if !ok {
- return Value{}
- }
- return v.Method(m.Index)
-}
-
-// NumField returns the number of fields in the struct v.
-// It panics if v's Kind is not Struct.
-func (v Value) NumField() int {
- v.mustBe(Struct)
- tt := (*structType)(unsafe.Pointer(v.typ))
- return len(tt.fields)
-}
-
-// OverflowComplex returns true if the complex128 x cannot be represented by v's type.
-// It panics if v's Kind is not Complex64 or Complex128.
-func (v Value) OverflowComplex(x complex128) bool {
- k := v.kind()
- switch k {
- case Complex64:
- return overflowFloat32(real(x)) || overflowFloat32(imag(x))
- case Complex128:
- return false
- }
- panic(&ValueError{"reflect.Value.OverflowComplex", k})
-}
-
-// OverflowFloat returns true if the float64 x cannot be represented by v's type.
-// It panics if v's Kind is not Float32 or Float64.
-func (v Value) OverflowFloat(x float64) bool {
- k := v.kind()
- switch k {
- case Float32:
- return overflowFloat32(x)
- case Float64:
- return false
- }
- panic(&ValueError{"reflect.Value.OverflowFloat", k})
-}
-
-func overflowFloat32(x float64) bool {
- if x < 0 {
- x = -x
- }
- return math.MaxFloat32 < x && x <= math.MaxFloat64
-}
-
-// OverflowInt returns true if the int64 x cannot be represented by v's type.
-// It panics if v's Kind is not Int, Int8, int16, Int32, or Int64.
-func (v Value) OverflowInt(x int64) bool {
- k := v.kind()
- switch k {
- case Int, Int8, Int16, Int32, Int64:
- bitSize := v.typ.size * 8
- trunc := (x << (64 - bitSize)) >> (64 - bitSize)
- return x != trunc
- }
- panic(&ValueError{"reflect.Value.OverflowInt", k})
-}
-
-// OverflowUint returns true if the uint64 x cannot be represented by v's type.
-// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
-func (v Value) OverflowUint(x uint64) bool {
- k := v.kind()
- switch k {
- case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
- bitSize := v.typ.size * 8
- trunc := (x << (64 - bitSize)) >> (64 - bitSize)
- return x != trunc
- }
- panic(&ValueError{"reflect.Value.OverflowUint", k})
-}
-
-// Pointer returns v's value as a uintptr.
-// It returns uintptr instead of unsafe.Pointer so that
-// code using reflect cannot obtain unsafe.Pointers
-// without importing the unsafe package explicitly.
-// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
-//
-// If v's Kind is Func, the returned pointer is an underlying
-// code pointer, but not necessarily enough to identify a
-// single function uniquely. The only guarantee is that the
-// result is zero if and only if v is a nil func Value.
-//
-// If v's Kind is Slice, the returned pointer is to the first
-// element of the slice. If the slice is nil the returned value
-// is 0. If the slice is empty but non-nil the return value is non-zero.
-func (v Value) Pointer() uintptr {
- // TODO: deprecate
- k := v.kind()
- switch k {
- case Chan, Map, Ptr, UnsafePointer:
- return uintptr(v.pointer())
- case Func:
- if v.flag&flagMethod != 0 {
- // As the doc comment says, the returned pointer is an
- // underlying code pointer but not necessarily enough to
- // identify a single function uniquely. All method expressions
- // created via reflect have the same underlying code pointer,
- // so their Pointers are equal. The function used here must
- // match the one used in makeMethodValue.
- f := methodValueCall
- return **(**uintptr)(unsafe.Pointer(&f))
- }
- p := v.pointer()
- // Non-nil func value points at data block.
- // First word of data block is actual code.
- if p != nil {
- p = *(*unsafe.Pointer)(p)
- }
- return uintptr(p)
-
- case Slice:
- return (*SliceHeader)(v.ptr).Data
- }
- panic(&ValueError{"reflect.Value.Pointer", k})
-}
-
-// Recv receives and returns a value from the channel v.
-// It panics if v's Kind is not Chan.
-// The receive blocks until a value is ready.
-// The boolean value ok is true if the value x corresponds to a send
-// on the channel, false if it is a zero value received because the channel is closed.
-func (v Value) Recv() (x Value, ok bool) {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.recv(false)
-}
-
-// internal recv, possibly non-blocking (nb).
-// v is known to be a channel.
-func (v Value) recv(nb bool) (val Value, ok bool) {
- tt := (*chanType)(unsafe.Pointer(v.typ))
- if ChanDir(tt.dir)&RecvDir == 0 {
- panic("reflect: recv on send-only channel")
- }
- t := tt.elem
- val = Value{t, nil, 0, flag(t.Kind()) << flagKindShift}
- var p unsafe.Pointer
- if t.size > ptrSize {
- p = unsafe_New(t)
- val.ptr = p
- val.flag |= flagIndir
- } else if t.pointers() {
- p = unsafe.Pointer(&val.ptr)
- } else {
- p = unsafe.Pointer(&val.scalar)
- }
- selected, ok := chanrecv(v.typ, v.pointer(), nb, p)
- if !selected {
- val = Value{}
- }
- return
-}
-
-// Send sends x on the channel v.
-// It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
-// As in Go, x's value must be assignable to the channel's element type.
-func (v Value) Send(x Value) {
- v.mustBe(Chan)
- v.mustBeExported()
- v.send(x, false)
-}
-
-// internal send, possibly non-blocking.
-// v is known to be a channel.
-func (v Value) send(x Value, nb bool) (selected bool) {
- tt := (*chanType)(unsafe.Pointer(v.typ))
- if ChanDir(tt.dir)&SendDir == 0 {
- panic("reflect: send on recv-only channel")
- }
- x.mustBeExported()
- x = x.assignTo("reflect.Value.Send", tt.elem, nil)
- var p unsafe.Pointer
- if x.flag&flagIndir != 0 {
- p = x.ptr
- } else if x.typ.pointers() {
- p = unsafe.Pointer(&x.ptr)
- } else {
- p = unsafe.Pointer(&x.scalar)
- }
- return chansend(v.typ, v.pointer(), p, nb)
-}
-
-// Set assigns x to the value v.
-// It panics if CanSet returns false.
-// As in Go, x's value must be assignable to v's type.
-func (v Value) Set(x Value) {
- v.mustBeAssignable()
- x.mustBeExported() // do not let unexported x leak
- var target *interface{}
- if v.kind() == Interface {
- target = (*interface{})(v.ptr)
- }
- x = x.assignTo("reflect.Set", v.typ, target)
- if x.flag&flagIndir != 0 {
- memmove(v.ptr, x.ptr, v.typ.size)
- } else if x.typ.pointers() {
- *(*unsafe.Pointer)(v.ptr) = x.ptr
- } else {
- memmove(v.ptr, unsafe.Pointer(&x.scalar), v.typ.size)
- }
-}
-
-// SetBool sets v's underlying value.
-// It panics if v's Kind is not Bool or if CanSet() is false.
-func (v Value) SetBool(x bool) {
- v.mustBeAssignable()
- v.mustBe(Bool)
- *(*bool)(v.ptr) = x
-}
-
-// SetBytes sets v's underlying value.
-// It panics if v's underlying value is not a slice of bytes.
-func (v Value) SetBytes(x []byte) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- if v.typ.Elem().Kind() != Uint8 {
- panic("reflect.Value.SetBytes of non-byte slice")
- }
- *(*[]byte)(v.ptr) = 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.ptr) = 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.
-func (v Value) SetComplex(x complex128) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetComplex", k})
- case Complex64:
- *(*complex64)(v.ptr) = complex64(x)
- case Complex128:
- *(*complex128)(v.ptr) = x
- }
-}
-
-// SetFloat sets v's underlying value to x.
-// It panics if v's Kind is not Float32 or Float64, or if CanSet() is false.
-func (v Value) SetFloat(x float64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetFloat", k})
- case Float32:
- *(*float32)(v.ptr) = float32(x)
- case Float64:
- *(*float64)(v.ptr) = x
- }
-}
-
-// SetInt sets v's underlying value to x.
-// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false.
-func (v Value) SetInt(x int64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetInt", k})
- case Int:
- *(*int)(v.ptr) = int(x)
- case Int8:
- *(*int8)(v.ptr) = int8(x)
- case Int16:
- *(*int16)(v.ptr) = int16(x)
- case Int32:
- *(*int32)(v.ptr) = int32(x)
- case Int64:
- *(*int64)(v.ptr) = x
- }
-}
-
-// SetLen sets v's length to n.
-// It panics if v's Kind is not Slice or if n is negative or
-// greater than the capacity of the slice.
-func (v Value) SetLen(n int) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- s := (*sliceHeader)(v.ptr)
- if n < 0 || n > int(s.Cap) {
- panic("reflect: slice length out of range in SetLen")
- }
- s.Len = n
-}
-
-// SetCap sets v's capacity to n.
-// It panics if v's Kind is not Slice or if n is smaller than the length or
-// greater than the capacity of the slice.
-func (v Value) SetCap(n int) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- s := (*sliceHeader)(v.ptr)
- if n < int(s.Len) || n > int(s.Cap) {
- panic("reflect: slice capacity out of range in SetCap")
- }
- s.Cap = n
-}
-
-// SetMapIndex sets the value associated with key in the map v to val.
-// It panics if v's Kind is not Map.
-// If val is the zero Value, SetMapIndex deletes the key from the map.
-// Otherwise if v holds a nil map, SetMapIndex will panic.
-// As in Go, key's value must be assignable to the map's key type,
-// and val's value must be assignable to the map's value type.
-func (v Value) SetMapIndex(key, val Value) {
- v.mustBe(Map)
- v.mustBeExported()
- key.mustBeExported()
- tt := (*mapType)(unsafe.Pointer(v.typ))
- key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
- var k unsafe.Pointer
- if key.flag&flagIndir != 0 {
- k = key.ptr
- } else if key.typ.pointers() {
- k = unsafe.Pointer(&key.ptr)
- } else {
- k = unsafe.Pointer(&key.scalar)
- }
- if val.typ == nil {
- mapdelete(v.typ, v.pointer(), k)
- return
- }
- val.mustBeExported()
- val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
- var e unsafe.Pointer
- if val.flag&flagIndir != 0 {
- e = val.ptr
- } else if val.typ.pointers() {
- e = unsafe.Pointer(&val.ptr)
- } else {
- e = unsafe.Pointer(&val.scalar)
- }
- mapassign(v.typ, v.pointer(), k, e)
-}
-
-// SetUint sets v's underlying value to x.
-// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
-func (v Value) SetUint(x uint64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetUint", k})
- case Uint:
- *(*uint)(v.ptr) = uint(x)
- case Uint8:
- *(*uint8)(v.ptr) = uint8(x)
- case Uint16:
- *(*uint16)(v.ptr) = uint16(x)
- case Uint32:
- *(*uint32)(v.ptr) = uint32(x)
- case Uint64:
- *(*uint64)(v.ptr) = x
- case Uintptr:
- *(*uintptr)(v.ptr) = uintptr(x)
- }
-}
-
-// SetPointer sets the unsafe.Pointer value v to x.
-// It panics if v's Kind is not UnsafePointer.
-func (v Value) SetPointer(x unsafe.Pointer) {
- v.mustBeAssignable()
- v.mustBe(UnsafePointer)
- *(*unsafe.Pointer)(v.ptr) = x
-}
-
-// SetString sets v's underlying value to x.
-// It panics if v's Kind is not String or if CanSet() is false.
-func (v Value) SetString(x string) {
- v.mustBeAssignable()
- v.mustBe(String)
- *(*string)(v.ptr) = x
-}
-
-// Slice returns v[i:j].
-// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array,
-// or if the indexes are out of bounds.
-func (v Value) Slice(i, j int) Value {
- var (
- cap int
- typ *sliceType
- base unsafe.Pointer
- )
- switch kind := v.kind(); kind {
- default:
- panic(&ValueError{"reflect.Value.Slice", kind})
-
- case Array:
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Slice: slice of unaddressable array")
- }
- tt := (*arrayType)(unsafe.Pointer(v.typ))
- cap = int(tt.len)
- typ = (*sliceType)(unsafe.Pointer(tt.slice))
- base = v.ptr
-
- case Slice:
- typ = (*sliceType)(unsafe.Pointer(v.typ))
- s := (*sliceHeader)(v.ptr)
- base = unsafe.Pointer(s.Data)
- cap = s.Cap
-
- case String:
- s := (*stringHeader)(v.ptr)
- if i < 0 || j < i || j > s.Len {
- panic("reflect.Value.Slice: string slice index out of bounds")
- }
- t := stringHeader{unsafe.Pointer(uintptr(s.Data) + uintptr(i)), j - i}
- return Value{v.typ, unsafe.Pointer(&t), 0, v.flag}
- }
-
- if i < 0 || j < i || j > cap {
- panic("reflect.Value.Slice: slice index out of bounds")
- }
-
- // Declare slice so that gc can see the base pointer in it.
- var x []unsafe.Pointer
-
- // Reinterpret as *sliceHeader to edit.
- s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
- s.Len = j - i
- s.Cap = cap - i
-
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x), 0, fl}
-}
-
-// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
-// It panics if v's Kind is not Array or Slice, or if v is an unaddressable array,
-// or if the indexes are out of bounds.
-func (v Value) Slice3(i, j, k int) Value {
- var (
- cap int
- typ *sliceType
- base unsafe.Pointer
- )
- switch kind := v.kind(); kind {
- default:
- panic(&ValueError{"reflect.Value.Slice3", kind})
-
- case Array:
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Slice3: slice of unaddressable array")
- }
- tt := (*arrayType)(unsafe.Pointer(v.typ))
- cap = int(tt.len)
- typ = (*sliceType)(unsafe.Pointer(tt.slice))
- base = v.ptr
-
- case Slice:
- typ = (*sliceType)(unsafe.Pointer(v.typ))
- s := (*sliceHeader)(v.ptr)
- base = s.Data
- cap = s.Cap
- }
-
- if i < 0 || j < i || k < j || k > cap {
- panic("reflect.Value.Slice3: slice index out of bounds")
- }
-
- // Declare slice so that the garbage collector
- // can see the base pointer in it.
- var x []unsafe.Pointer
-
- // Reinterpret as *sliceHeader to edit.
- s := (*sliceHeader)(unsafe.Pointer(&x))
- s.Data = unsafe.Pointer(uintptr(base) + uintptr(i)*typ.elem.Size())
- s.Len = j - i
- s.Cap = k - i
-
- fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
- return Value{typ.common(), unsafe.Pointer(&x), 0, fl}
-}
-
-// String returns the string v's underlying value, as a string.
-// String is a special case because of Go's String method convention.
-// Unlike the other getters, it does not panic if v's Kind is not String.
-// Instead, it returns a string of the form "<T value>" where T is v's type.
-func (v Value) String() string {
- switch k := v.kind(); k {
- case Invalid:
- return "<invalid Value>"
- case String:
- return *(*string)(v.ptr)
- }
- // If you call String on a reflect.Value of other type, it's better to
- // print something than to panic. Useful in debugging.
- return "<" + v.typ.String() + " Value>"
-}
-
-// TryRecv attempts to receive a value from the channel v but will not block.
-// It panics if v's Kind is not Chan.
-// If the receive delivers a value, x is the transferred value and ok is true.
-// If the receive cannot finish without blocking, x is the zero Value and ok is false.
-// If the channel is closed, x is the zero value for the channel's element type and ok is false.
-func (v Value) TryRecv() (x Value, ok bool) {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.recv(true)
-}
-
-// TrySend attempts to send x on the channel v but will not block.
-// It panics if v's Kind is not Chan.
-// It returns true if the value was sent, false otherwise.
-// As in Go, x's value must be assignable to the channel's element type.
-func (v Value) TrySend(x Value) bool {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.send(x, true)
-}
-
-// Type returns v's type.
-func (v Value) Type() Type {
- f := v.flag
- if f == 0 {
- panic(&ValueError{"reflect.Value.Type", Invalid})
- }
- if f&flagMethod == 0 {
- // Easy case
- return v.typ
- }
-
- // Method value.
- // v.typ describes the receiver, not the method type.
- i := int(v.flag) >> flagMethodShift
- if v.typ.Kind() == Interface {
- // Method on interface.
- tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
- panic("reflect: internal error: invalid method index")
- }
- m := &tt.methods[i]
- return m.typ
- }
- // Method on concrete type.
- ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
- panic("reflect: internal error: invalid method index")
- }
- m := &ut.methods[i]
- return m.mtyp
-}
-
-// Uint returns v's underlying value, as a uint64.
-// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
-func (v Value) Uint() uint64 {
- k := v.kind()
- var p unsafe.Pointer
- if v.flag&flagIndir != 0 {
- p = v.ptr
- } else {
- // The escape analysis is good enough that &v.scalar
- // does not trigger a heap allocation.
- p = unsafe.Pointer(&v.scalar)
- }
- switch k {
- case Uint:
- return uint64(*(*uint)(p))
- case Uint8:
- return uint64(*(*uint8)(p))
- case Uint16:
- return uint64(*(*uint16)(p))
- case Uint32:
- return uint64(*(*uint32)(p))
- case Uint64:
- return uint64(*(*uint64)(p))
- case Uintptr:
- return uint64(*(*uintptr)(p))
- }
- panic(&ValueError{"reflect.Value.Uint", k})
-}
-
-// UnsafeAddr returns a pointer to v's data.
-// It is for advanced clients that also import the "unsafe" package.
-// It panics if v is not addressable.
-func (v Value) UnsafeAddr() uintptr {
- // TODO: deprecate
- if v.typ == nil {
- panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
- }
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.UnsafeAddr of unaddressable value")
- }
- return uintptr(v.ptr)
-}
-
-// StringHeader is the runtime representation of a string.
-// It cannot be used safely or portably and its representation may
-// change in a later release.
-// Moreover, the Data field is not sufficient to guarantee the data
-// it references will not be garbage collected, so programs must keep
-// a separate, correctly typed pointer to the underlying data.
-type StringHeader struct {
- Data uintptr
- Len int
-}
-
-// stringHeader is a safe version of StringHeader used within this package.
-type stringHeader struct {
- Data unsafe.Pointer
- Len int
-}
-
-// SliceHeader is the runtime representation of a slice.
-// It cannot be used safely or portably and its representation may
-// change in a later release.
-// Moreover, the Data field is not sufficient to guarantee the data
-// it references will not be garbage collected, so programs must keep
-// a separate, correctly typed pointer to the underlying data.
-type SliceHeader struct {
- Data uintptr
- Len int
- Cap int
-}
-
-// sliceHeader is a safe version of SliceHeader used within this package.
-type sliceHeader struct {
- Data unsafe.Pointer
- Len int
- Cap int
-}
-
-func typesMustMatch(what string, t1, t2 Type) {
- if t1 != t2 {
- panic(what + ": " + t1.String() + " != " + t2.String())
- }
-}
-
-// grow grows the slice s so that it can hold extra more values, allocating
-// more capacity if needed. It also returns the old and new slice lengths.
-func grow(s Value, extra int) (Value, int, int) {
- i0 := s.Len()
- i1 := i0 + extra
- if i1 < i0 {
- panic("reflect.Append: slice overflow")
- }
- m := s.Cap()
- if i1 <= m {
- return s.Slice(0, i1), i0, i1
- }
- if m == 0 {
- m = extra
- } else {
- for m < i1 {
- if i0 < 1024 {
- m += m
- } else {
- m += m / 4
- }
- }
- }
- t := MakeSlice(s.Type(), i1, m)
- Copy(t, s)
- return t, i0, i1
-}
-
-// Append appends the values x to a slice s and returns the resulting slice.
-// As in Go, each x's value must be assignable to the slice's element type.
-func Append(s Value, x ...Value) Value {
- s.mustBe(Slice)
- s, i0, i1 := grow(s, len(x))
- for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
- s.Index(i).Set(x[j])
- }
- return s
-}
-
-// AppendSlice appends a slice t to a slice s and returns the resulting slice.
-// The slices s and t must have the same element type.
-func AppendSlice(s, t Value) Value {
- s.mustBe(Slice)
- t.mustBe(Slice)
- typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
- s, i0, i1 := grow(s, t.Len())
- Copy(s.Slice(i0, i1), t)
- return s
-}
-
-// Copy copies the contents of src into dst until either
-// dst has been filled or src has been exhausted.
-// It returns the number of elements copied.
-// Dst and src each must have kind Slice or Array, and
-// dst and src must have the same element type.
-func Copy(dst, src Value) int {
- dk := dst.kind()
- if dk != Array && dk != Slice {
- panic(&ValueError{"reflect.Copy", dk})
- }
- if dk == Array {
- dst.mustBeAssignable()
- }
- dst.mustBeExported()
-
- sk := src.kind()
- if sk != Array && sk != Slice {
- panic(&ValueError{"reflect.Copy", sk})
- }
- src.mustBeExported()
-
- de := dst.typ.Elem()
- se := src.typ.Elem()
- typesMustMatch("reflect.Copy", de, se)
-
- n := dst.Len()
- if sn := src.Len(); n > sn {
- n = sn
- }
-
- // If sk is an in-line array, cannot take its address.
- // Instead, copy element by element.
- // TODO: memmove would be ok for this (sa = unsafe.Pointer(&v.scalar))
- // if we teach the compiler that ptrs don't escape from memmove.
- if src.flag&flagIndir == 0 {
- for i := 0; i < n; i++ {
- dst.Index(i).Set(src.Index(i))
- }
- return n
- }
-
- // Copy via memmove.
- var da, sa unsafe.Pointer
- if dk == Array {
- da = dst.ptr
- } else {
- da = (*sliceHeader)(dst.ptr).Data
- }
- if sk == Array {
- sa = src.ptr
- } else {
- sa = (*sliceHeader)(src.ptr).Data
- }
- memmove(da, sa, uintptr(n)*de.Size())
- return n
-}
-
-// A runtimeSelect is a single case passed to rselect.
-// This must match ../runtime/chan.c:/runtimeSelect
-type runtimeSelect struct {
- dir uintptr // 0, SendDir, or RecvDir
- typ *rtype // channel type
- ch unsafe.Pointer // channel
- val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir)
-}
-
-// rselect runs a select. It returns the index of the chosen case.
-// If the case was a receive, val is filled in with the received value.
-// The conventional OK bool indicates whether the receive corresponds
-// to a sent value.
-//go:noescape
-func rselect([]runtimeSelect) (chosen int, recvOK bool)
-
-// A SelectDir describes the communication direction of a select case.
-type SelectDir int
-
-// NOTE: These values must match ../runtime/chan.c:/SelectDir.
-
-const (
- _ SelectDir = iota
- SelectSend // case Chan <- Send
- SelectRecv // case <-Chan:
- SelectDefault // default
-)
-
-// A SelectCase describes a single case in a select operation.
-// The kind of case depends on Dir, the communication direction.
-//
-// If Dir is SelectDefault, the case represents a default case.
-// Chan and Send must be zero Values.
-//
-// If Dir is SelectSend, the case represents a send operation.
-// Normally Chan's underlying value must be a channel, and Send's underlying value must be
-// assignable to the channel's element type. As a special case, if Chan is a zero Value,
-// then the case is ignored, and the field Send will also be ignored and may be either zero
-// or non-zero.
-//
-// If Dir is SelectRecv, the case represents a receive operation.
-// Normally Chan's underlying value must be a channel and Send must be a zero Value.
-// If Chan is a zero Value, then the case is ignored, but Send must still be a zero Value.
-// When a receive operation is selected, the received Value is returned by Select.
-//
-type SelectCase struct {
- Dir SelectDir // direction of case
- Chan Value // channel to use (for send or receive)
- Send Value // value to send (for send)
-}
-
-// Select executes a select operation described by the list of cases.
-// Like the Go select statement, it blocks until at least one of the cases
-// can proceed, makes a uniform pseudo-random choice,
-// and then executes that case. It returns the index of the chosen case
-// and, if that case was a receive operation, the value received and a
-// boolean indicating whether the value corresponds to a send on the channel
-// (as opposed to a zero value received because the channel is closed).
-func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
- // NOTE: Do not trust that caller is not modifying cases data underfoot.
- // The range is safe because the caller cannot modify our copy of the len
- // and each iteration makes its own copy of the value c.
- runcases := make([]runtimeSelect, len(cases))
- haveDefault := false
- for i, c := range cases {
- rc := &runcases[i]
- rc.dir = uintptr(c.Dir)
- switch c.Dir {
- default:
- panic("reflect.Select: invalid Dir")
-
- case SelectDefault: // default
- if haveDefault {
- panic("reflect.Select: multiple default cases")
- }
- haveDefault = true
- if c.Chan.IsValid() {
- panic("reflect.Select: default case has Chan value")
- }
- if c.Send.IsValid() {
- panic("reflect.Select: default case has Send value")
- }
-
- case SelectSend:
- ch := c.Chan
- if !ch.IsValid() {
- break
- }
- ch.mustBe(Chan)
- ch.mustBeExported()
- tt := (*chanType)(unsafe.Pointer(ch.typ))
- if ChanDir(tt.dir)&SendDir == 0 {
- panic("reflect.Select: SendDir case using recv-only channel")
- }
- rc.ch = ch.pointer()
- rc.typ = &tt.rtype
- v := c.Send
- if !v.IsValid() {
- panic("reflect.Select: SendDir case missing Send value")
- }
- v.mustBeExported()
- v = v.assignTo("reflect.Select", tt.elem, nil)
- if v.flag&flagIndir != 0 {
- rc.val = v.ptr
- } else if v.typ.pointers() {
- rc.val = unsafe.Pointer(&v.ptr)
- } else {
- rc.val = unsafe.Pointer(&v.scalar)
- }
-
- case SelectRecv:
- if c.Send.IsValid() {
- panic("reflect.Select: RecvDir case has Send value")
- }
- ch := c.Chan
- if !ch.IsValid() {
- break
- }
- ch.mustBe(Chan)
- ch.mustBeExported()
- tt := (*chanType)(unsafe.Pointer(ch.typ))
- if ChanDir(tt.dir)&RecvDir == 0 {
- panic("reflect.Select: RecvDir case using send-only channel")
- }
- rc.ch = ch.pointer()
- rc.typ = &tt.rtype
- rc.val = unsafe_New(tt.elem)
- }
- }
-
- chosen, recvOK = rselect(runcases)
- if runcases[chosen].dir == uintptr(SelectRecv) {
- tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
- t := tt.elem
- p := runcases[chosen].val
- fl := flag(t.Kind()) << flagKindShift
- if t.size > ptrSize {
- recv = Value{t, p, 0, fl | flagIndir}
- } else if t.pointers() {
- recv = Value{t, *(*unsafe.Pointer)(p), 0, fl}
- } else {
- recv = Value{t, nil, loadScalar(p, t.size), fl}
- }
- }
- return chosen, recv, recvOK
-}
-
-/*
- * constructors
- */
-
-// implemented in package runtime
-func unsafe_New(*rtype) unsafe.Pointer
-func unsafe_NewArray(*rtype, int) unsafe.Pointer
-
-// MakeSlice creates a new zero-initialized slice value
-// for the specified slice type, length, and capacity.
-func MakeSlice(typ Type, len, cap int) Value {
- if typ.Kind() != Slice {
- panic("reflect.MakeSlice of non-slice type")
- }
- if len < 0 {
- panic("reflect.MakeSlice: negative len")
- }
- if cap < 0 {
- panic("reflect.MakeSlice: negative cap")
- }
- if len > cap {
- panic("reflect.MakeSlice: len > cap")
- }
-
- s := sliceHeader{unsafe_NewArray(typ.Elem().(*rtype), cap), len, cap}
- return Value{typ.common(), unsafe.Pointer(&s), 0, flagIndir | flag(Slice)<<flagKindShift}
-}
-
-// MakeChan creates a new channel with the specified type and buffer size.
-func MakeChan(typ Type, buffer int) Value {
- if typ.Kind() != Chan {
- panic("reflect.MakeChan of non-chan type")
- }
- if buffer < 0 {
- panic("reflect.MakeChan: negative buffer size")
- }
- if typ.ChanDir() != BothDir {
- panic("reflect.MakeChan: unidirectional channel type")
- }
- ch := makechan(typ.(*rtype), uint64(buffer))
- return Value{typ.common(), ch, 0, flag(Chan) << flagKindShift}
-}
-
-// MakeMap creates a new map of the specified type.
-func MakeMap(typ Type) Value {
- if typ.Kind() != Map {
- panic("reflect.MakeMap of non-map type")
- }
- m := makemap(typ.(*rtype))
- return Value{typ.common(), m, 0, flag(Map) << flagKindShift}
-}
-
-// Indirect returns the value that v points to.
-// If v is a nil pointer, Indirect returns a zero Value.
-// If v is not a pointer, Indirect returns v.
-func Indirect(v Value) Value {
- if v.Kind() != Ptr {
- return v
- }
- return v.Elem()
-}
-
-// ValueOf returns a new Value initialized to the concrete value
-// stored in the interface i. ValueOf(nil) returns the zero Value.
-func ValueOf(i interface{}) Value {
- if i == nil {
- return Value{}
- }
-
- // TODO(rsc): Eliminate this terrible hack.
- // In the call to unpackEface, i.typ doesn't escape,
- // and i.word is an integer. So it looks like
- // i doesn't escape. But really it does,
- // because i.word is actually a pointer.
- escapes(i)
-
- return unpackEface(i)
-}
-
-// Zero returns a Value representing the zero value for the specified type.
-// The result is different from the zero value of the Value struct,
-// which represents no value at all.
-// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
-// The returned value is neither addressable nor settable.
-func Zero(typ Type) Value {
- if typ == nil {
- panic("reflect: Zero(nil)")
- }
- t := typ.common()
- fl := flag(t.Kind()) << flagKindShift
- if t.size <= ptrSize {
- return Value{t, nil, 0, fl}
- }
- return Value{t, unsafe_New(typ.(*rtype)), 0, fl | flagIndir}
-}
-
-// New returns a Value representing a pointer to a new zero value
-// for the specified type. That is, the returned Value's Type is PtrTo(typ).
-func New(typ Type) Value {
- if typ == nil {
- panic("reflect: New(nil)")
- }
- ptr := unsafe_New(typ.(*rtype))
- fl := flag(Ptr) << flagKindShift
- return Value{typ.common().ptrTo(), ptr, 0, fl}
-}
-
-// NewAt returns a Value representing a pointer to a value of the
-// specified type, using p as that pointer.
-func NewAt(typ Type, p unsafe.Pointer) Value {
- fl := flag(Ptr) << flagKindShift
- return Value{typ.common().ptrTo(), p, 0, fl}
-}
-
-// assignTo returns a value v that can be assigned directly to typ.
-// It panics if v is not assignable to typ.
-// For a conversion to an interface type, target is a suggested scratch space to use.
-func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
- if v.flag&flagMethod != 0 {
- v = makeMethodValue(context, v)
- }
-
- switch {
- case directlyAssignable(dst, v.typ):
- // Overwrite type so that they match.
- // Same memory layout, so no harm done.
- v.typ = dst
- fl := v.flag & (flagRO | flagAddr | flagIndir)
- fl |= flag(dst.Kind()) << flagKindShift
- return Value{dst, v.ptr, v.scalar, fl}
-
- case implements(dst, v.typ):
- if target == nil {
- target = new(interface{})
- }
- x := valueInterface(v, false)
- if dst.NumMethod() == 0 {
- *target = x
- } else {
- ifaceE2I(dst, x, unsafe.Pointer(target))
- }
- return Value{dst, unsafe.Pointer(target), 0, flagIndir | flag(Interface)<<flagKindShift}
- }
-
- // Failed.
- 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 {
- v = makeMethodValue("Convert", v)
- }
- 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 *rtype) 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(typ)
- *(*uint64)(unsafe.Pointer(ptr)) = bits
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
- var s uintptr
- switch typ.size {
- case 1:
- *(*uint8)(unsafe.Pointer(&s)) = uint8(bits)
- case 2:
- *(*uint16)(unsafe.Pointer(&s)) = uint16(bits)
- case 4:
- *(*uint32)(unsafe.Pointer(&s)) = uint32(bits)
- case 8:
- *(*uint64)(unsafe.Pointer(&s)) = uint64(bits)
- }
- return Value{typ, nil, s, 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(typ)
- *(*float64)(unsafe.Pointer(ptr)) = v
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
-
- var s uintptr
- switch typ.size {
- case 4:
- *(*float32)(unsafe.Pointer(&s)) = float32(v)
- case 8:
- *(*float64)(unsafe.Pointer(&s)) = v
- }
- return Value{typ, nil, s, 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(typ)
- switch typ.size {
- case 8:
- *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
- case 16:
- *(*complex128)(unsafe.Pointer(ptr)) = v
- }
- return Value{typ, ptr, 0, f | flagIndir | flag(typ.Kind())<<flagKindShift}
- }
-
- // Assume ptrSize <= 8 so this must be complex64.
- var s uintptr
- *(*complex64)(unsafe.Pointer(&s)) = complex64(v)
- return Value{typ, nil, s, 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()
- ptr := v.ptr
- if f&flagAddr != 0 {
- // indirect, mutable word - make a copy
- c := unsafe_New(t)
- memmove(c, ptr, t.size)
- ptr = c
- f &^= flagAddr
- }
- return Value{t, ptr, v.scalar, v.flag&flagRO | f} // v.flag&flagRO|f == 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.(*rtype), x, unsafe.Pointer(target))
- }
- return Value{typ.common(), unsafe.Pointer(target), 0, 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
-func chancap(ch unsafe.Pointer) int
-func chanclose(ch unsafe.Pointer)
-func chanlen(ch unsafe.Pointer) int
-
-//go:noescape
-func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
-
-//go:noescape
-func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool
-
-func makechan(typ *rtype, size uint64) (ch unsafe.Pointer)
-func makemap(t *rtype) (m unsafe.Pointer)
-func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
-func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
-func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer)
-func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer
-func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
-func mapiternext(it unsafe.Pointer)
-func maplen(m unsafe.Pointer) int
-
-func call(fn, arg unsafe.Pointer, n uint32, retoffset uint32)
-func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
-
-// Dummy annotation marking that the value x escapes,
-// for use in cases where the reflect code is so clever that
-// the compiler cannot follow.
-func escapes(x interface{}) {
- if dummy.b {
- dummy.x = x
- }
-}
-
-var dummy struct {
- b bool
- x interface{}
-}