Source file test/escape_iface.go

     1  // errorcheck -0 -m -l
     2  
     3  // Copyright 2015 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test escape analysis for interface conversions.
     8  
     9  package escape
    10  
    11  var sink interface{}
    12  
    13  type M interface {
    14  	M()
    15  }
    16  
    17  func mescapes(m M) { // ERROR "leaking param: m"
    18  	sink = m
    19  }
    20  
    21  func mdoesnotescape(m M) { // ERROR "m does not escape"
    22  }
    23  
    24  // Tests for type stored directly in iface and with value receiver method.
    25  type M0 struct {
    26  	p *int
    27  }
    28  
    29  func (M0) M() {
    30  }
    31  
    32  func efaceEscape0() {
    33  	{
    34  		i := 0
    35  		v := M0{&i}
    36  		var x M = v
    37  		_ = x
    38  	}
    39  	{
    40  		i := 0 // ERROR "moved to heap: i"
    41  		v := M0{&i}
    42  		var x M = v
    43  		sink = x
    44  	}
    45  	{
    46  		i := 0
    47  		v := M0{&i}
    48  		var x M = v
    49  		v1 := x.(M0)
    50  		_ = v1
    51  	}
    52  	{
    53  		i := 0 // ERROR "moved to heap: i"
    54  		v := M0{&i}
    55  		// BAD: v does not escape to heap here
    56  		var x M = v
    57  		v1 := x.(M0)
    58  		sink = v1
    59  	}
    60  	{
    61  		i := 0
    62  		v := M0{&i}
    63  		var x M = v
    64  		x.M() // ERROR "devirtualizing x.M"
    65  	}
    66  	{
    67  		i := 0 // ERROR "moved to heap: i"
    68  		v := M0{&i}
    69  		var x M = v
    70  		mescapes(x)
    71  	}
    72  	{
    73  		i := 0
    74  		v := M0{&i}
    75  		var x M = v
    76  		mdoesnotescape(x)
    77  	}
    78  }
    79  
    80  // Tests for type stored indirectly in iface and with value receiver method.
    81  type M1 struct {
    82  	p *int
    83  	x int
    84  }
    85  
    86  func (M1) M() {
    87  }
    88  
    89  func efaceEscape1() {
    90  	{
    91  		i := 0
    92  		v := M1{&i, 0}
    93  		var x M = v // ERROR "v does not escape"
    94  		_ = x
    95  	}
    96  	{
    97  		i := 0 // ERROR "moved to heap: i"
    98  		v := M1{&i, 0}
    99  		var x M = v // ERROR "v escapes to heap"
   100  		sink = x
   101  	}
   102  	{
   103  		i := 0
   104  		v := M1{&i, 0}
   105  		var x M = v // ERROR "v does not escape"
   106  		v1 := x.(M1)
   107  		_ = v1
   108  	}
   109  	{
   110  		i := 0 // ERROR "moved to heap: i"
   111  		v := M1{&i, 0}
   112  		var x M = v // ERROR "v does not escape"
   113  		v1 := x.(M1)
   114  		sink = v1 // ERROR "v1 escapes to heap"
   115  	}
   116  	{
   117  		i := 0
   118  		v := M1{&i, 0}
   119  		var x M = v // ERROR "v does not escape"
   120  		x.M()       // ERROR "devirtualizing x.M"
   121  	}
   122  	{
   123  		i := 0 // ERROR "moved to heap: i"
   124  		v := M1{&i, 0}
   125  		var x M = v // ERROR "v escapes to heap"
   126  		mescapes(x)
   127  	}
   128  	{
   129  		i := 0
   130  		v := M1{&i, 0}
   131  		var x M = v // ERROR "v does not escape"
   132  		mdoesnotescape(x)
   133  	}
   134  }
   135  
   136  // Tests for type stored directly in iface and with pointer receiver method.
   137  type M2 struct {
   138  	p *int
   139  }
   140  
   141  func (*M2) M() {
   142  }
   143  
   144  func efaceEscape2() {
   145  	{
   146  		i := 0
   147  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   148  		var x M = v
   149  		_ = x
   150  	}
   151  	{
   152  		i := 0       // ERROR "moved to heap: i"
   153  		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
   154  		var x M = v
   155  		sink = x
   156  	}
   157  	{
   158  		i := 0
   159  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   160  		var x M = v
   161  		v1 := x.(*M2)
   162  		_ = v1
   163  	}
   164  	{
   165  		i := 0       // ERROR "moved to heap: i"
   166  		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
   167  		// BAD: v does not escape to heap here
   168  		var x M = v
   169  		v1 := x.(*M2)
   170  		sink = v1
   171  	}
   172  	{
   173  		i := 0       // ERROR "moved to heap: i"
   174  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   175  		// BAD: v does not escape to heap here
   176  		var x M = v
   177  		v1 := x.(*M2)
   178  		sink = *v1
   179  	}
   180  	{
   181  		i := 0       // ERROR "moved to heap: i"
   182  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   183  		// BAD: v does not escape to heap here
   184  		var x M = v
   185  		v1, ok := x.(*M2)
   186  		sink = *v1
   187  		_ = ok
   188  	}
   189  	{
   190  		i := 0
   191  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   192  		var x M = v
   193  		x.M() // ERROR "devirtualizing x.M"
   194  	}
   195  	{
   196  		i := 0       // ERROR "moved to heap: i"
   197  		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
   198  		var x M = v
   199  		mescapes(x)
   200  	}
   201  	{
   202  		i := 0
   203  		v := &M2{&i} // ERROR "&M2{...} does not escape"
   204  		var x M = v
   205  		mdoesnotescape(x)
   206  	}
   207  }
   208  
   209  type T1 struct {
   210  	p *int
   211  }
   212  
   213  type T2 struct {
   214  	T1 T1
   215  }
   216  
   217  func dotTypeEscape() *T2 { // #11931
   218  	var x interface{}
   219  	x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1{...} does not escape"
   220  	return &T2{          // ERROR "&T2{...} escapes to heap"
   221  		T1: *(x.(*T1)),
   222  	}
   223  }
   224  
   225  func dotTypeEscape2() { // #13805, #15796
   226  	{
   227  		i := 0
   228  		j := 0
   229  		var v int
   230  		var ok bool
   231  		var x interface{} = i // ERROR "i does not escape"
   232  		var y interface{} = j // ERROR "j does not escape"
   233  
   234  		*(&v) = x.(int)
   235  		*(&v), *(&ok) = y.(int)
   236  	}
   237  	{ // #13805, #15796
   238  		i := 0
   239  		j := 0
   240  		var ok bool
   241  		var x interface{} = i // ERROR "i does not escape"
   242  		var y interface{} = j // ERROR "j does not escape"
   243  
   244  		sink = x.(int)         // ERROR "x.\(int\) escapes to heap"
   245  		sink, *(&ok) = y.(int) // ERROR "autotmp_.* escapes to heap"
   246  	}
   247  	{
   248  		i := 0 // ERROR "moved to heap: i"
   249  		j := 0 // ERROR "moved to heap: j"
   250  		var ok bool
   251  		var x interface{} = &i
   252  		var y interface{} = &j
   253  
   254  		sink = x.(*int)
   255  		sink, *(&ok) = y.(*int)
   256  	}
   257  }
   258  
   259  func issue42279() {
   260  	type I interface{ M() }
   261  	type T struct{ I }
   262  
   263  	var i I = T{} // ERROR "T\{\} does not escape"
   264  	i.M()         // ERROR "partially devirtualizing i.M to T"
   265  }
   266  

View as plain text