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  }