go/pointer/testdata/mapreflect.go
Alan Donovan d7a9805478 go.tools/pointer: use assignable not identical type predicate in reflect.{Send,SetMapIndex,etc}
Various reflect operations permit assignability conversions,
i.e. their internals behave unlike y=x.(T) which unpacks only
those interface values in x that are identical to T.

We split typeAssertConstraint y=x.(T) into two constraints:
1) typeFilter, for when T is an interface type and no
   representation change occurs.
2) unpack, for when T is a concrete type and the payload of the
   tagged object is extracted.  This constraint has an 'exact'
   parameter indicating whether to use the predicate
   IsIdentical (for type assertions) or
   IsAssignable (for reflect operators).

+ Tests.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14547043
2013-10-14 13:53:41 -04:00

104 lines
3.2 KiB
Go

// +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 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()
reflectSetMapIndexAssignable()
reflectMakeMap()
// TODO(adonovan): reflect.MapOf(Type)
}