1 | //go:build ignore |
---|---|
2 | // +build ignore |
3 | |
4 | package main |
5 | |
6 | import ( |
7 | "reflect" |
8 | "unsafe" |
9 | ) |
10 | |
11 | var a, b int |
12 | var unknown bool |
13 | |
14 | func reflectIndirect() { |
15 | ptr := &a |
16 | // Pointer: |
17 | print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto command-line-arguments.a |
18 | // Non-pointer: |
19 | print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto command-line-arguments.a |
20 | } |
21 | |
22 | func reflectNewAt() { |
23 | var x [8]byte |
24 | print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int |
25 | } |
26 | |
27 | // @warning "unsound: command-line-arguments.reflectNewAt contains a reflect.NewAt.. call" |
28 | |
29 | func reflectTypeOf() { |
30 | t := reflect.TypeOf(3) |
31 | if unknown { |
32 | t = reflect.TypeOf("foo") |
33 | } |
34 | // TODO(adonovan): make types.Eval let us refer to unexported types. |
35 | print(t) // #@types *reflect.rtype |
36 | print(reflect.Zero(t).Interface()) // @types int | string |
37 | newint := reflect.New(t).Interface() // @line rtonew |
38 | print(newint) // @types *int | *string |
39 | print(newint.(*int)) // @pointsto <alloc in reflect.New> |
40 | print(newint.(*string)) // @pointsto <alloc in reflect.New> |
41 | } |
42 | |
43 | func reflectTypeElem() { |
44 | print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface()) // @types int |
45 | print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface()) // @types string |
46 | print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface()) // @types bool |
47 | print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64 |
48 | print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface()) // @types complex64 |
49 | print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface()) // @types |
50 | print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem())) // @types interface{} |
51 | print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface()) // @types |
52 | } |
53 | |
54 | // reflect.Values within reflect.Values. |
55 | func metareflection() { |
56 | // "box" a *int twice, unbox it twice. |
57 | v0 := reflect.ValueOf(&a) |
58 | print(v0) // @types *int |
59 | v1 := reflect.ValueOf(v0) // box |
60 | print(v1) // @types reflect.Value |
61 | v2 := reflect.ValueOf(v1) // box |
62 | print(v2) // @types reflect.Value |
63 | v1a := v2.Interface().(reflect.Value) // unbox |
64 | print(v1a) // @types reflect.Value |
65 | v0a := v1a.Interface().(reflect.Value) // unbox |
66 | print(v0a) // @types *int |
67 | print(v0a.Interface().(*int)) // @pointsto command-line-arguments.a |
68 | |
69 | // "box" an interface{} lvalue twice, unbox it twice. |
70 | var iface interface{} = 3 |
71 | x0 := reflect.ValueOf(&iface).Elem() |
72 | print(x0) // @types interface{} |
73 | x1 := reflect.ValueOf(x0) // box |
74 | print(x1) // @types reflect.Value |
75 | x2 := reflect.ValueOf(x1) // box |
76 | print(x2) // @types reflect.Value |
77 | x1a := x2.Interface().(reflect.Value) // unbox |
78 | print(x1a) // @types reflect.Value |
79 | x0a := x1a.Interface().(reflect.Value) // unbox |
80 | print(x0a) // @types interface{} |
81 | print(x0a.Interface()) // @types int |
82 | } |
83 | |
84 | type T struct{} |
85 | |
86 | // When the output of a type constructor flows to its input, we must |
87 | // bound the set of types created to ensure termination of the algorithm. |
88 | func typeCycle() { |
89 | t := reflect.TypeOf(0) |
90 | u := reflect.TypeOf("") |
91 | v := reflect.TypeOf(T{}) |
92 | for unknown { |
93 | t = reflect.PtrTo(t) |
94 | t = reflect.SliceOf(t) |
95 | |
96 | u = reflect.SliceOf(u) |
97 | |
98 | if unknown { |
99 | v = reflect.ChanOf(reflect.BothDir, v) |
100 | } else { |
101 | v = reflect.PtrTo(v) |
102 | } |
103 | } |
104 | |
105 | // Type height is bounded to about 4 map/slice/chan/pointer constructors. |
106 | print(reflect.Zero(t).Interface()) // @types int | []*int | []*[]*int |
107 | print(reflect.Zero(u).Interface()) // @types string | []string | [][]string | [][][]string | [][][][]string |
108 | print(reflect.Zero(v).Interface()) // @types T | *T | **T | ***T | ****T | chan T | *chan T | **chan T | chan *T | *chan *T | chan **T | chan ***T | chan chan T | chan *chan T | chan chan *T |
109 | } |
110 | |
111 | func main() { |
112 | reflectIndirect() |
113 | reflectNewAt() |
114 | reflectTypeOf() |
115 | reflectTypeElem() |
116 | metareflection() |
117 | typeCycle() |
118 | } |
119 |
Members