// +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 for _, k := range keys { print(k) // @pointsto 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 print(zmap.Interface()) // @pointsto print(tmap.Key()) // @pointsto *int print(tmap.Elem()) // @pointsto *bool print(reflect.Zero(tmap.Key())) // @pointsto print(reflect.Zero(tmap.Key()).Interface()) // @pointsto print(reflect.Zero(tmap.Key()).Interface()) // @types *int print(reflect.Zero(tmap.Elem())) // @pointsto print(reflect.Zero(tmap.Elem()).Interface()) // @pointsto 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 } func main() { reflectMapKeysIndex() reflectSetMapIndex() reflectSetMapIndexInterface() reflectSetMapIndexAssignable() reflectMakeMap() // TODO(adonovan): reflect.MapOf(Type) }