Source file test/closure3.dir/main.go

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Check correctness of various closure corner cases
     6  // that are expected to be inlined
     7  
     8  package main
     9  
    10  var ok bool
    11  var sink int
    12  
    13  func main() {
    14  	{
    15  		if x := func() int { // ERROR "can inline main.func1"
    16  			return 1
    17  		}(); x != 1 { // ERROR "inlining call to main.func1"
    18  			ppanic("x != 1")
    19  		}
    20  		if x := func() int { // ERROR "can inline main.func2" "func literal does not escape"
    21  			return 1
    22  		}; x() != 1 { // ERROR "inlining call to main.func2"
    23  			_ = x // prevent simple deadcode elimination after inlining
    24  			ppanic("x() != 1")
    25  		}
    26  	}
    27  
    28  	{
    29  		if y := func(x int) int { // ERROR "can inline main.func3"
    30  			return x + 2
    31  		}(40); y != 42 { // ERROR "inlining call to main.func3"
    32  			ppanic("y != 42")
    33  		}
    34  		if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
    35  			return x + 2
    36  		}; y(40) != 42 { // ERROR "inlining call to main.func4"
    37  			_ = y // prevent simple deadcode elimination after inlining
    38  			ppanic("y(40) != 42")
    39  		}
    40  	}
    41  
    42  	{
    43  		y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape"
    44  			return x + 2
    45  		}
    46  		y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape"
    47  			return x + 1
    48  		}
    49  		if y(40) != 41 {
    50  			ppanic("y(40) != 41")
    51  		}
    52  	}
    53  
    54  	{
    55  		func() { // ERROR "can inline main.func7"
    56  			y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape"
    57  				return x + 2
    58  			}
    59  			y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape"
    60  				return x + 1
    61  			}
    62  			if y(40) != 41 {
    63  				ppanic("y(40) != 41")
    64  			}
    65  		}() // ERROR "func literal does not escape" "inlining call to main.func7"
    66  	}
    67  
    68  	{
    69  		y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape"
    70  			return x + 2
    71  		}
    72  		y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape"
    73  			return x + 1
    74  		}, 42
    75  		if y(40) != 41 {
    76  			ppanic("y(40) != 41")
    77  		}
    78  	}
    79  
    80  	{
    81  		func() { // ERROR "can inline main.func10"
    82  			y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape"
    83  				return x + 2
    84  			}
    85  			y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape"
    86  				return x + 1
    87  			}, 42
    88  			if y(40) != 41 {
    89  				ppanic("y(40) != 41")
    90  			}
    91  		}() // ERROR "func literal does not escape" "inlining call to main.func10"
    92  	}
    93  
    94  	{
    95  		y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
    96  			return x + 2
    97  		}
    98  		y, sink = func() (func(int) int, int) { // ERROR "can inline main.func12"
    99  			return func(x int) int { // ERROR "can inline main.func12" "func literal escapes to heap"
   100  				return x + 1
   101  			}, 42
   102  		}() // ERROR "func literal does not escape" "inlining call to main.func12"
   103  		if y(40) != 41 {
   104  			ppanic("y(40) != 41")
   105  		}
   106  	}
   107  
   108  	{
   109  		func() { // ERROR "can inline main.func13"
   110  			y := func(x int) int { // ERROR "func literal does not escape" "can inline main.func13.1"
   111  				return x + 2
   112  			}
   113  			y, sink = func() (func(int) int, int) { // ERROR "can inline main.func13.2" "can inline main.main.func13.func35"
   114  				return func(x int) int { // ERROR   "can inline main.func13.2" "func literal escapes to heap"
   115  					return x + 1
   116  				}, 42
   117  			}() // ERROR "func literal does not escape" "inlining call to main.func13.2"
   118  			if y(40) != 41 {
   119  				ppanic("y(40) != 41")
   120  			}
   121  		}() // ERROR "func literal does not escape" "inlining call to main.func13" "inlining call to main.main.func13.func35"
   122  	}
   123  
   124  	{
   125  		y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
   126  			return x + 2
   127  		}
   128  		y, ok = map[int]func(int) int{ // ERROR "does not escape"
   129  			0: func(x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
   130  		}[0]
   131  		if y(40) != 41 {
   132  			ppanic("y(40) != 41")
   133  		}
   134  	}
   135  
   136  	{
   137  		func() { // ERROR "can inline main.func16"
   138  			y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
   139  				return x + 2
   140  			}
   141  			y, ok = map[int]func(int) int{ // ERROR "does not escape"
   142  				0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
   143  			}[0]
   144  			if y(40) != 41 {
   145  				ppanic("y(40) != 41")
   146  			}
   147  		}() // ERROR "func literal does not escape" "inlining call to main.func16" "map\[int\]func\(int\) int{...} does not escape" "func literal escapes to heap"
   148  	}
   149  
   150  	{
   151  		y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
   152  			return x + 2
   153  		}
   154  		y, ok = interface{}(func(x int) int { // ERROR "can inline main.func18" "does not escape"
   155  			return x + 1
   156  		}).(func(int) int)
   157  		if y(40) != 41 {
   158  			ppanic("y(40) != 41")
   159  		}
   160  	}
   161  
   162  	{
   163  		func() { // ERROR "can inline main.func19"
   164  			y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape"
   165  				return x + 2
   166  			}
   167  			y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape"
   168  				return x + 1
   169  			}).(func(int) int)
   170  			if y(40) != 41 {
   171  				ppanic("y(40) != 41")
   172  			}
   173  		}() // ERROR "func literal does not escape" "inlining call to main.func19"
   174  	}
   175  
   176  	{
   177  		x := 42
   178  		if y := func() int { // ERROR "can inline main.func20"
   179  			return x
   180  		}(); y != 42 { // ERROR "inlining call to main.func20"
   181  			ppanic("y != 42")
   182  		}
   183  		if y := func() int { // ERROR "can inline main.func21" "func literal does not escape"
   184  			return x
   185  		}; y() != 42 { // ERROR "inlining call to main.func21"
   186  			_ = y // prevent simple deadcode elimination after inlining
   187  			ppanic("y() != 42")
   188  		}
   189  	}
   190  
   191  	{
   192  		x := 42
   193  		if z := func(y int) int { // ERROR "can inline main.func22"
   194  			return func() int { // ERROR "can inline main.func22.1" "can inline main.main.func22.func40"
   195  				return x + y
   196  			}() // ERROR "inlining call to main.func22.1"
   197  		}(1); z != 43 { // ERROR "inlining call to main.func22" "inlining call to main.main.func22.func40"
   198  			ppanic("z != 43")
   199  		}
   200  		if z := func(y int) int { // ERROR "func literal does not escape" "can inline main.func23"
   201  			return func() int { // ERROR "can inline main.func23.1" "can inline main.main.func23.func41"
   202  				return x + y
   203  			}() // ERROR "inlining call to main.func23.1"
   204  		}; z(1) != 43 { // ERROR "inlining call to main.func23" "inlining call to main.main.func23.func41"
   205  			_ = z // prevent simple deadcode elimination after inlining
   206  			ppanic("z(1) != 43")
   207  		}
   208  	}
   209  
   210  	{
   211  		a := 1
   212  		func() { // ERROR "can inline main.func24"
   213  			func() { // ERROR "can inline main.func24" "can inline main.main.func24.func42"
   214  				a = 2
   215  			}() // ERROR "inlining call to main.func24"
   216  		}() // ERROR "inlining call to main.func24" "inlining call to main.main.func24.func42"
   217  		if a != 2 {
   218  			ppanic("a != 2")
   219  		}
   220  	}
   221  
   222  	{
   223  		b := 2
   224  		func(b int) { // ERROR "can inline main.func25"
   225  			func() { // ERROR "can inline main.func25.1" "can inline main.main.func25.func43"
   226  				b = 3
   227  			}() // ERROR "inlining call to main.func25.1"
   228  			if b != 3 {
   229  				ppanic("b != 3")
   230  			}
   231  		}(b) // ERROR "inlining call to main.func25" "inlining call to main.main.func25.func43"
   232  		if b != 2 {
   233  			ppanic("b != 2")
   234  		}
   235  	}
   236  
   237  	{
   238  		c := 3
   239  		func() { // ERROR "can inline main.func26"
   240  			c = 4
   241  			func() {
   242  				if c != 4 {
   243  					ppanic("c != 4")
   244  				}
   245  				recover() // prevent inlining
   246  			}()
   247  		}() // ERROR "inlining call to main.func26" "func literal does not escape"
   248  		if c != 4 {
   249  			ppanic("c != 4")
   250  		}
   251  	}
   252  
   253  	{
   254  		a := 2
   255  		// This has an unfortunate exponential growth, where as we visit each
   256  		// function, we inline the inner closure, and that constructs a new
   257  		// function for any closures inside the inner function, and then we
   258  		// revisit those. E.g., func34 and func36 are constructed by the inliner.
   259  		if r := func(x int) int { // ERROR "can inline main.func27"
   260  			b := 3
   261  			return func(y int) int { // ERROR "can inline main.func27.1" "can inline main.main.func27.func45"
   262  				c := 5
   263  				return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.main.func27.func45.1" "can inline main.func27.main.func27.1.2" "can inline main.main.func27.main.main.func27.func45.func48"
   264  					return a*x + b*y + c*z
   265  				}(10) // ERROR "inlining call to main.func27.1.1"
   266  			}(100) // ERROR "inlining call to main.func27.1" "inlining call to main.func27.main.func27.1.2"
   267  		}(1000); r != 2350 { // ERROR "inlining call to main.func27" "inlining call to main.main.func27.func45" "inlining call to main.main.func27.main.main.func27.func45.func48"
   268  			ppanic("r != 2350")
   269  		}
   270  	}
   271  
   272  	{
   273  		a := 2
   274  		if r := func(x int) int { // ERROR "can inline main.func28"
   275  			b := 3
   276  			return func(y int) int { // ERROR "can inline main.func28.1" "can inline main.main.func28.func46"
   277  				c := 5
   278  				func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.main.func28.1.2" "can inline main.main.func28.func46.1" "can inline main.main.func28.main.main.func28.func46.func49"
   279  					a = a * x
   280  					b = b * y
   281  					c = c * z
   282  				}(10) // ERROR "inlining call to main.func28.1.1"
   283  				return a + c
   284  			}(100) + b // ERROR "inlining call to main.func28.1" "inlining call to main.func28.main.func28.1.2"
   285  		}(1000); r != 2350 { // ERROR "inlining call to main.func28" "inlining call to main.main.func28.func46" "inlining call to main.main.func28.main.main.func28.func46.func49"
   286  			ppanic("r != 2350")
   287  		}
   288  		if a != 2000 {
   289  			ppanic("a != 2000")
   290  		}
   291  	}
   292  }
   293  
   294  //go:noinline
   295  func notmain() {
   296  	{
   297  		// This duplicates the first block in main, but without the "_ = x" for closure x.
   298  		// This allows dead code elimination of x before escape analysis,
   299  		// thus "func literal does not escape" should not appear.
   300  		if x := func() int { // ERROR "can inline notmain.func1"
   301  			return 1
   302  		}(); x != 1 { // ERROR "inlining call to notmain.func1"
   303  			ppanic("x != 1")
   304  		}
   305  		if x := func() int { // ERROR "can inline notmain.func2"
   306  			return 1
   307  		}; x() != 1 { // ERROR "inlining call to notmain.func2"
   308  			ppanic("x() != 1")
   309  		}
   310  	}
   311  }
   312  
   313  //go:noinline
   314  func ppanic(s string) { // ERROR "leaking param: s"
   315  	panic(s) // ERROR "s escapes to heap"
   316  }
   317  

View as plain text