1// +build ignore 2 3package main 4 5import "reflect" 6import "unsafe" 7 8var a, b int 9var unknown bool 10 11func reflectIndirect() { 12 ptr := &a 13 // Pointer: 14 print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto main.a 15 // Non-pointer: 16 print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto main.a 17} 18 19func reflectNewAt() { 20 var x [8]byte 21 print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int 22} 23 24// @warning "unsound: main.reflectNewAt contains a reflect.NewAt.. call" 25 26func reflectTypeOf() { 27 t := reflect.TypeOf(3) 28 if unknown { 29 t = reflect.TypeOf("foo") 30 } 31 // TODO(adonovan): make types.Eval let us refer to unexported types. 32 print(t) // #@types *reflect.rtype 33 print(reflect.Zero(t).Interface()) // @types int | string 34 newint := reflect.New(t).Interface() // @line rtonew 35 print(newint) // @types *int | *string 36 print(newint.(*int)) // @pointsto <alloc in reflect.New> 37 print(newint.(*string)) // @pointsto <alloc in reflect.New> 38} 39 40func reflectTypeElem() { 41 print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface()) // @types int 42 print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface()) // @types string 43 print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface()) // @types bool 44 print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64 45 print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface()) // @types complex64 46 print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface()) // @types 47 print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem())) // @types interface{} 48 print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface()) // @types 49} 50 51// reflect.Values within reflect.Values. 52func metareflection() { 53 // "box" a *int twice, unbox it twice. 54 v0 := reflect.ValueOf(&a) 55 print(v0) // @types *int 56 v1 := reflect.ValueOf(v0) // box 57 print(v1) // @types reflect.Value 58 v2 := reflect.ValueOf(v1) // box 59 print(v2) // @types reflect.Value 60 v1a := v2.Interface().(reflect.Value) // unbox 61 print(v1a) // @types reflect.Value 62 v0a := v1a.Interface().(reflect.Value) // unbox 63 print(v0a) // @types *int 64 print(v0a.Interface().(*int)) // @pointsto main.a 65 66 // "box" an interface{} lvalue twice, unbox it twice. 67 var iface interface{} = 3 68 x0 := reflect.ValueOf(&iface).Elem() 69 print(x0) // @types interface{} 70 x1 := reflect.ValueOf(x0) // box 71 print(x1) // @types reflect.Value 72 x2 := reflect.ValueOf(x1) // box 73 print(x2) // @types reflect.Value 74 x1a := x2.Interface().(reflect.Value) // unbox 75 print(x1a) // @types reflect.Value 76 x0a := x1a.Interface().(reflect.Value) // unbox 77 print(x0a) // @types interface{} 78 print(x0a.Interface()) // @types int 79} 80 81type T struct{} 82 83// When the output of a type constructor flows to its input, we must 84// bound the set of types created to ensure termination of the algorithm. 85func typeCycle() { 86 t := reflect.TypeOf(0) 87 u := reflect.TypeOf("") 88 v := reflect.TypeOf(T{}) 89 for unknown { 90 t = reflect.PtrTo(t) 91 t = reflect.SliceOf(t) 92 93 u = reflect.SliceOf(u) 94 95 if unknown { 96 v = reflect.ChanOf(reflect.BothDir, v) 97 } else { 98 v = reflect.PtrTo(v) 99 } 100 } 101 102 // Type height is bounded to about 4 map/slice/chan/pointer constructors. 103 print(reflect.Zero(t).Interface()) // @types int | []*int | []*[]*int 104 print(reflect.Zero(u).Interface()) // @types string | []string | [][]string | [][][]string | [][][][]string 105 print(reflect.Zero(v).Interface()) // @types T | *T | **T | ***T | ****T | chan T | *chan T | **chan T | chan *T | *chan *T | chan **T | chan ***T | chan chan T | chan *chan T | chan chan *T 106} 107 108func main() { 109 reflectIndirect() 110 reflectNewAt() 111 reflectTypeOf() 112 reflectTypeElem() 113 metareflection() 114 typeCycle() 115} 116