mirror of
https://github.com/golang/go
synced 2024-11-19 06:24:41 -07:00
94c387c610
The implementation follows the basic pattern of an indirect function call (genDynamicCall). We use the same trick as SetFinalizer so that direct calls to (r.V).Call, which are overwhelmingly the norm, are inlined. Bug fix (and simplification): calling untag() to unbox a reflect.Value is wrong for reflect.Values containing interfaces (rare). Now, we call untag for concrete types and typeFilter for interface types, and we can use this pattern in all cases. It corresponds to the ssa.TypeAssert operator, so we call it typeAssert. Added tests to cover this. We also specialize reflect.{In,Out} when the operand is an int literal. + Tests. Also: - make taggedValue() panic, not return nil, eliminating many checks. We call isTaggedValue for the one place that cares. - pointer_test: recover from panics in Analyze() and dump the log. R=crawshaw CC=golang-dev https://golang.org/cl/14426050
118 lines
3.7 KiB
Go
118 lines
3.7 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 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)
|
|
}
|