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