mirror of
https://github.com/golang/go.git
synced 2025-05-08 09:03:04 +00:00
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
88 lines
3.3 KiB
Go
88 lines
3.3 KiB
Go
// +build ignore
|
|
|
|
package main
|
|
|
|
import "reflect"
|
|
import "unsafe"
|
|
|
|
var a, b int
|
|
var unknown bool
|
|
|
|
func reflectIndirect() {
|
|
ptr := &a
|
|
// Pointer:
|
|
print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto main.a
|
|
// Non-pointer:
|
|
print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto main.a
|
|
}
|
|
|
|
func reflectNewAt() {
|
|
var x [8]byte
|
|
print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int
|
|
}
|
|
|
|
// @warning "unsound: main.reflectNewAt contains a reflect.NewAt.. call"
|
|
|
|
func reflectTypeOf() {
|
|
t := reflect.TypeOf(3)
|
|
if unknown {
|
|
t = reflect.TypeOf("foo")
|
|
}
|
|
// TODO(adonovan): make types.Eval let us refer to unexported types.
|
|
print(t) // #@types *reflect.rtype
|
|
print(reflect.Zero(t).Interface()) // @types int | string
|
|
newint := reflect.New(t).Interface() // @line rtonew
|
|
print(newint) // @types *int | *string
|
|
print(newint.(*int)) // @pointsto <alloc in reflect.New>
|
|
print(newint.(*string)) // @pointsto <alloc in reflect.New>
|
|
}
|
|
|
|
func reflectTypeElem() {
|
|
print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface()) // @types int
|
|
print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface()) // @types string
|
|
print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface()) // @types bool
|
|
print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64
|
|
print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface()) // @types complex64
|
|
print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface()) // @types
|
|
print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem())) // @types interface{}
|
|
print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface()) // @types
|
|
}
|
|
|
|
// reflect.Values within reflect.Values.
|
|
func metareflection() {
|
|
// "box" a *int twice, unbox it twice.
|
|
v0 := reflect.ValueOf(&a)
|
|
print(v0) // @types *int
|
|
v1 := reflect.ValueOf(v0) // box
|
|
print(v1) // @types reflect.Value
|
|
v2 := reflect.ValueOf(v1) // box
|
|
print(v2) // @types reflect.Value
|
|
v1a := v2.Interface().(reflect.Value) // unbox
|
|
print(v1a) // @types reflect.Value
|
|
v0a := v1a.Interface().(reflect.Value) // unbox
|
|
print(v0a) // @types *int
|
|
print(v0a.Interface().(*int)) // @pointsto main.a
|
|
|
|
// "box" an interface{} lvalue twice, unbox it twice.
|
|
var iface interface{} = 3
|
|
x0 := reflect.ValueOf(&iface).Elem()
|
|
print(x0) // @types interface{}
|
|
x1 := reflect.ValueOf(x0) // box
|
|
print(x1) // @types reflect.Value
|
|
x2 := reflect.ValueOf(x1) // box
|
|
print(x2) // @types reflect.Value
|
|
x1a := x2.Interface().(reflect.Value) // unbox
|
|
print(x1a) // @types reflect.Value
|
|
x0a := x1a.Interface().(reflect.Value) // unbox
|
|
print(x0a) // @types interface{}
|
|
print(x0a.Interface()) // @types int
|
|
}
|
|
|
|
func main() {
|
|
reflectIndirect()
|
|
reflectNewAt()
|
|
reflectTypeOf()
|
|
reflectTypeElem()
|
|
metareflection()
|
|
}
|