github.com/v2fly/tools@v0.100.0/go/pointer/testdata/interfaces.go (about) 1 // +build ignore 2 3 package main 4 5 type I interface { 6 f() 7 } 8 9 type C int 10 11 func (*C) f() {} 12 13 type D struct{ ptr *int } 14 15 func (D) f() {} 16 17 type E struct{} 18 19 func (*E) f() {} 20 21 var a, b int 22 23 var unknown bool // defeat dead-code elimination 24 25 func 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 46 func 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 77 func 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 87 func 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 110 type J interface { 111 f(*int) *int 112 } 113 114 type P struct { 115 x int 116 } 117 118 func (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 124 func 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 136 func 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 145 func main() { 146 interface1() 147 interface2() 148 interface3() 149 interface4() 150 interface5() 151 interface6() 152 }