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