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  }