116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.2 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
 | |
| }
 | |
| 
 | |
| 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()
 | |
| }
 |