mirror of
https://github.com/golang/go.git
synced 2025-05-07 08:32:59 +00:00
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
104 lines
3.2 KiB
Go
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)
|
|
}
|