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