mapreflect.go
3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// +build ignore
package main
// Test of maps with reflection.
import "reflect"
var a int
var b bool
func reflectMapKeysIndex() {
m := make(map[*int]*bool) // @line mr1make
m[&a] = &b
mrv := reflect.ValueOf(m)
print(mrv.Interface()) // @types map[*int]*bool
print(mrv.Interface().(map[*int]*bool)) // @pointsto makemap@mr1make:11
print(mrv) // @pointsto makeinterface:map[*int]*bool
print(mrv) // @types map[*int]*bool
keys := mrv.MapKeys()
print(keys) // @pointsto <alloc in (reflect.Value).MapKeys>
for _, k := range keys {
print(k) // @pointsto <alloc in (reflect.Value).MapKeys>
print(k) // @types *int
print(k.Interface()) // @types *int
print(k.Interface().(*int)) // @pointsto main.a
v := mrv.MapIndex(k)
print(v.Interface()) // @types *bool
print(v.Interface().(*bool)) // @pointsto main.b
}
}
func reflectSetMapIndex() {
m := make(map[*int]*bool)
mrv := reflect.ValueOf(m)
mrv.SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
print(m[nil]) // @pointsto main.b
for _, k := range mrv.MapKeys() {
print(k.Interface()) // @types *int
print(k.Interface().(*int)) // @pointsto main.a
}
tmap := reflect.TypeOf(m)
// types.EvalNode won't let us refer to non-exported types:
// print(tmap) // #@types *reflect.rtype
print(tmap) // @pointsto map[*int]*bool
zmap := reflect.Zero(tmap)
print(zmap) // @pointsto <alloc in reflect.Zero>
print(zmap.Interface()) // @pointsto <alloc in reflect.Zero>
print(tmap.Key()) // @pointsto *int
print(tmap.Elem()) // @pointsto *bool
print(reflect.Zero(tmap.Key())) // @pointsto <alloc in reflect.Zero>
print(reflect.Zero(tmap.Key()).Interface()) // @pointsto <alloc in reflect.Zero>
print(reflect.Zero(tmap.Key()).Interface()) // @types *int
print(reflect.Zero(tmap.Elem())) // @pointsto <alloc in reflect.Zero>
print(reflect.Zero(tmap.Elem()).Interface()) // @pointsto <alloc in reflect.Zero>
print(reflect.Zero(tmap.Elem()).Interface()) // @types *bool
}
func reflectSetMapIndexInterface() {
// Exercises reflect.Value conversions to/from interfaces:
// a different code path than for concrete types.
m := make(map[interface{}]interface{})
reflect.ValueOf(m).SetMapIndex(reflect.ValueOf(&a), reflect.ValueOf(&b))
for k, v := range m {
print(k) // @types *int
print(k.(*int)) // @pointsto main.a
print(v) // @types *bool
print(v.(*bool)) // @pointsto main.b
}
}
func reflectSetMapIndexAssignable() {
// SetMapIndex performs implicit assignability conversions.
type I *int
type J *int
str := reflect.ValueOf("")
// *int is assignable to I.
m1 := make(map[string]I)
reflect.ValueOf(m1).SetMapIndex(str, reflect.ValueOf(new(int))) // @line int
print(m1[""]) // @pointsto new@int:58
// I is assignable to I.
m2 := make(map[string]I)
reflect.ValueOf(m2).SetMapIndex(str, reflect.ValueOf(I(new(int)))) // @line I
print(m2[""]) // @pointsto new@I:60
// J is not assignable to I.
m3 := make(map[string]I)
reflect.ValueOf(m3).SetMapIndex(str, reflect.ValueOf(J(new(int))))
print(m3[""]) // @pointsto
}
func reflectMakeMap() {
t := reflect.TypeOf(map[*int]*bool(nil))
v := reflect.MakeMap(t)
print(v) // @types map[*int]*bool
print(v) // @pointsto <alloc in reflect.MakeMap>
}
func main() {
reflectMapKeysIndex()
reflectSetMapIndex()
reflectSetMapIndexInterface()
reflectSetMapIndexAssignable()
reflectMakeMap()
// TODO(adonovan): reflect.MapOf(Type)
}