--- /dev/null
+// +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
+}
+
+type T struct{}
+
+// When the output of a type constructor flows to its input, we must
+// bound the set of types created to ensure termination of the algorithm.
+func typeCycle() {
+ t := reflect.TypeOf(0)
+ u := reflect.TypeOf("")
+ v := reflect.TypeOf(T{})
+ for unknown {
+ t = reflect.PtrTo(t)
+ t = reflect.SliceOf(t)
+
+ u = reflect.SliceOf(u)
+
+ if unknown {
+ v = reflect.ChanOf(reflect.BothDir, v)
+ } else {
+ v = reflect.PtrTo(v)
+ }
+ }
+
+ // Type height is bounded to about 4 map/slice/chan/pointer constructors.
+ print(reflect.Zero(t).Interface()) // @types int | []*int | []*[]*int
+ print(reflect.Zero(u).Interface()) // @types string | []string | [][]string | [][][]string | [][][][]string
+ 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
+}
+
+func main() {
+ reflectIndirect()
+ reflectNewAt()
+ reflectTypeOf()
+ reflectTypeElem()
+ metareflection()
+ typeCycle()
+}