1// +build ignore 2 3package main 4 5type I interface { 6 f() 7} 8 9type C int 10 11func (*C) f() {} 12 13type D struct{ ptr *int } 14 15func (D) f() {} 16 17type E struct{} 18 19func (*E) f() {} 20 21var a, b int 22 23var unknown bool // defeat dead-code elimination 24 25func interface1() { 26 var i interface{} = &a 27 var j interface{} = D{&b} 28 k := j 29 if unknown { 30 k = i 31 } 32 33 print(i) // @types *int 34 print(j) // @types D 35 print(k) // @types *int | D 36 37 print(i.(*int)) // @pointsto main.a 38 print(j.(*int)) // @pointsto 39 print(k.(*int)) // @pointsto main.a 40 41 print(i.(D).ptr) // @pointsto 42 print(j.(D).ptr) // @pointsto main.b 43 print(k.(D).ptr) // @pointsto main.b 44} 45 46func interface2() { 47 var i I = (*C)(&a) 48 var j I = D{&a} 49 k := j 50 if unknown { 51 k = i 52 } 53 54 print(i) // @types *C 55 print(j) // @types D 56 print(k) // @types *C | D 57 print(k) // @pointsto makeinterface:main.D | makeinterface:*main.C 58 59 k.f() 60 // @calls main.interface2 -> (*main.C).f 61 // @calls main.interface2 -> (main.D).f 62 63 print(i.(*C)) // @pointsto main.a 64 print(j.(D).ptr) // @pointsto main.a 65 print(k.(*C)) // @pointsto main.a 66 67 switch x := k.(type) { 68 case *C: 69 print(x) // @pointsto main.a 70 case D: 71 print(x.ptr) // @pointsto main.a 72 case *E: 73 print(x) // @pointsto 74 } 75} 76 77func interface3() { 78 // There should be no backflow of concrete types from the type-switch to x. 79 var x interface{} = 0 80 print(x) // @types int 81 switch x.(type) { 82 case int: 83 case string: 84 } 85} 86 87func interface4() { 88 var i interface{} = D{&a} 89 if unknown { 90 i = 123 91 } 92 93 print(i) // @types int | D 94 95 j := i.(I) // interface narrowing type-assertion 96 print(j) // @types D 97 print(j.(D).ptr) // @pointsto main.a 98 99 var l interface{} = j // interface widening assignment. 100 print(l) // @types D 101 print(l.(D).ptr) // @pointsto main.a 102 103 m := j.(interface{}) // interface widening type-assertion. 104 print(m) // @types D 105 print(m.(D).ptr) // @pointsto main.a 106} 107 108// Interface method calls and value flow: 109 110type J interface { 111 f(*int) *int 112} 113 114type P struct { 115 x int 116} 117 118func (p *P) f(pi *int) *int { 119 print(p) // @pointsto p@i5p:6 120 print(pi) // @pointsto i@i5i:6 121 return &p.x 122} 123 124func interface5() { 125 var p P // @line i5p 126 var j J = &p 127 var i int // @line i5i 128 print(j.f(&i)) // @pointsto p.x@i5p:6 129 print(&i) // @pointsto i@i5i:6 130 131 print(j) // @pointsto makeinterface:*main.P 132} 133 134// @calls main.interface5 -> (*main.P).f 135 136func interface6() { 137 f := I.f 138 print(f) // @pointsto (main.I).f$thunk 139 f(new(struct{ D })) 140} 141 142// @calls main.interface6 -> (main.I).f$thunk 143// @calls (main.I).f$thunk -> (*struct{main.D}).f 144 145func main() { 146 interface1() 147 interface2() 148 interface3() 149 interface4() 150 interface5() 151 interface6() 152} 153