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  			ppanic("x() != 1")
    24  		}
    25  	}
    26  
    27  	{
    28  		if y := func(x int) int { // ERROR "can inline main.func3"
    29  			return x + 2
    30  		}(40); y != 42 { // ERROR "inlining call to main.func3"
    31  			ppanic("y != 42")
    32  		}
    33  		if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
    34  			return x + 2
    35  		}; y(40) != 42 { // ERROR "inlining call to main.func4"
    36  			ppanic("y(40) != 42")
    37  		}
    38  	}
    39  
    40  	{
    41  		y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape"
    42  			return x + 2
    43  		}
    44  		y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape"
    45  			return x + 1
    46  		}
    47  		if y(40) != 41 {
    48  			ppanic("y(40) != 41")
    49  		}
    50  	}
    51  
    52  	{
    53  		func() { // ERROR "func literal does not escape"
    54  			y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape"
    55  				return x + 2
    56  			}
    57  			y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape"
    58  				return x + 1
    59  			}
    60  			if y(40) != 41 {
    61  				ppanic("y(40) != 41")
    62  			}
    63  		}()
    64  	}
    65  
    66  	{
    67  		y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape"
    68  			return x + 2
    69  		}
    70  		y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape"
    71  			return x + 1
    72  		}, 42
    73  		if y(40) != 41 {
    74  			ppanic("y(40) != 41")
    75  		}
    76  	}
    77  
    78  	{
    79  		func() { // ERROR "func literal does not escape"
    80  			y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape"
    81  				return x + 2
    82  			}
    83  			y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape"
    84  				return x + 1
    85  			}, 42
    86  			if y(40) != 41 {
    87  				ppanic("y(40) != 41")
    88  			}
    89  		}()
    90  	}
    91  
    92  	{
    93  		y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
    94  			return x + 2
    95  		}
    96  		y, sink = func() (func(int) int, int) { // ERROR "can inline main.func12"
    97  			return func(x int) int { // ERROR "can inline main.func12"
    98  				return x + 1
    99  			}, 42
   100  		}() // ERROR "func literal does not escape" "inlining call to main.func12"
   101  		if y(40) != 41 {
   102  			ppanic("y(40) != 41")
   103  		}
   104  	}
   105  
   106  	{
   107  		func() { // ERROR "func literal does not escape"
   108  			y := func(x int) int { // ERROR "func literal does not escape" "can inline main.func13.1"
   109  				return x + 2
   110  			}
   111  			y, sink = func() (func(int) int, int) { // ERROR "can inline main.func13.2"
   112  				return func(x int) int { // ERROR   "can inline main.func13.2"
   113  					return x + 1
   114  				}, 42
   115  			}() // ERROR "func literal does not escape" "inlining call to main.func13.2"
   116  			if y(40) != 41 {
   117  				ppanic("y(40) != 41")
   118  			}
   119  		}()
   120  	}
   121  
   122  	{
   123  		y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
   124  			return x + 2
   125  		}
   126  		y, ok = map[int]func(int) int{ // ERROR "does not escape"
   127  			0: func(x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
   128  		}[0]
   129  		if y(40) != 41 {
   130  			ppanic("y(40) != 41")
   131  		}
   132  	}
   133  
   134  	{
   135  		func() { // ERROR "func literal does not escape"
   136  			y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
   137  				return x + 2
   138  			}
   139  			y, ok = map[int]func(int) int{ // ERROR "does not escape"
   140  				0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
   141  			}[0]
   142  			if y(40) != 41 {
   143  				ppanic("y(40) != 41")
   144  			}
   145  		}()
   146  	}
   147  
   148  	{
   149  		y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
   150  			return x + 2
   151  		}
   152  		y, ok = interface{}(func(x int) int { // ERROR "can inline main.func18" "does not escape"
   153  			return x + 1
   154  		}).(func(int) int)
   155  		if y(40) != 41 {
   156  			ppanic("y(40) != 41")
   157  		}
   158  	}
   159  
   160  	{
   161  		func() { // ERROR "func literal does not escape"
   162  			y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape"
   163  				return x + 2
   164  			}
   165  			y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape"
   166  				return x + 1
   167  			}).(func(int) int)
   168  			if y(40) != 41 {
   169  				ppanic("y(40) != 41")
   170  			}
   171  		}()
   172  	}
   173  
   174  	{
   175  		x := 42
   176  		if y := func() int { // ERROR "can inline main.func20"
   177  			return x
   178  		}(); y != 42 { // ERROR "inlining call to main.func20"
   179  			ppanic("y != 42")
   180  		}
   181  		if y := func() int { // ERROR "can inline main.func21" "func literal does not escape"
   182  			return x
   183  		}; y() != 42 { // ERROR "inlining call to main.func21"
   184  			ppanic("y() != 42")
   185  		}
   186  	}
   187  
   188  	{
   189  		x := 42
   190  		if z := func(y int) int { // ERROR "can inline main.func22"
   191  			return func() int { // ERROR "can inline main.func22.1" "can inline main.main.func22.func30"
   192  				return x + y
   193  			}() // ERROR "inlining call to main.func22.1"
   194  		}(1); z != 43 { // ERROR "inlining call to main.func22" "inlining call to main.main.func22.func30"
   195  			ppanic("z != 43")
   196  		}
   197  		if z := func(y int) int { // ERROR "func literal does not escape" "can inline main.func23"
   198  			return func() int { // ERROR "can inline main.func23.1" "can inline main.main.func23.func31"
   199  				return x + y
   200  			}() // ERROR "inlining call to main.func23.1"
   201  		}; z(1) != 43 { // ERROR "inlining call to main.func23" "inlining call to main.main.func23.func31"
   202  			ppanic("z(1) != 43")
   203  		}
   204  	}
   205  
   206  	{
   207  		a := 1
   208  		func() { // ERROR "can inline main.func24"
   209  			func() { // ERROR "can inline main.func24" "can inline main.main.func24.func32"
   210  				a = 2
   211  			}() // ERROR "inlining call to main.func24"
   212  		}() // ERROR "inlining call to main.func24" "inlining call to main.main.func24.func32"
   213  		if a != 2 {
   214  			ppanic("a != 2")
   215  		}
   216  	}
   217  
   218  	{
   219  		b := 2
   220  		func(b int) { // ERROR "func literal does not escape"
   221  			func() { // ERROR "can inline main.func25.1"
   222  				b = 3
   223  			}() // ERROR "inlining call to main.func25.1"
   224  			if b != 3 {
   225  				ppanic("b != 3")
   226  			}
   227  		}(b)
   228  		if b != 2 {
   229  			ppanic("b != 2")
   230  		}
   231  	}
   232  
   233  	{
   234  		c := 3
   235  		func() { // ERROR "can inline main.func26"
   236  			c = 4
   237  			func() {
   238  				if c != 4 {
   239  					ppanic("c != 4")
   240  				}
   241  				recover() // prevent inlining
   242  			}()
   243  		}() // ERROR "inlining call to main.func26" "func literal does not escape"
   244  		if c != 4 {
   245  			ppanic("c != 4")
   246  		}
   247  	}
   248  
   249  	{
   250  		a := 2
   251  		// This has an unfortunate exponential growth, where as we visit each
   252  		// function, we inline the inner closure, and that constructs a new
   253  		// function for any closures inside the inner function, and then we
   254  		// revisit those. E.g., func34 and func36 are constructed by the inliner.
   255  		if r := func(x int) int { // ERROR "can inline main.func27"
   256  			b := 3
   257  			return func(y int) int { // ERROR "can inline main.func27.1" "can inline main.main.func27.func34"
   258  				c := 5
   259  				return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.main.func27.func34.1" "can inline main.func27.main.func27.1.2" "can inline main.main.func27.main.main.func27.func34.func36"
   260  					return a*x + b*y + c*z
   261  				}(10) // ERROR "inlining call to main.func27.1.1"
   262  			}(100) // ERROR "inlining call to main.func27.1" "inlining call to main.func27.main.func27.1.2"
   263  		}(1000); r != 2350 { // ERROR "inlining call to main.func27" "inlining call to main.main.func27.func34" "inlining call to main.main.func27.main.main.func27.func34.func36"
   264  			ppanic("r != 2350")
   265  		}
   266  	}
   267  
   268  	{
   269  		a := 2
   270  		if r := func(x int) int { // ERROR "can inline main.func28"
   271  			b := 3
   272  			return func(y int) int { // ERROR "can inline main.func28.1" "can inline main.main.func28.func35"
   273  				c := 5
   274  				func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.main.func28.1.2" "can inline main.main.func28.func35.1" "can inline main.main.func28.main.main.func28.func35.func37"
   275  					a = a * x
   276  					b = b * y
   277  					c = c * z
   278  				}(10) // ERROR "inlining call to main.func28.1.1"
   279  				return a + c
   280  			}(100) + b // ERROR "inlining call to main.func28.1" "inlining call to main.func28.main.func28.1.2"
   281  		}(1000); r != 2350 { // ERROR "inlining call to main.func28" "inlining call to main.main.func28.func35" "inlining call to main.main.func28.main.main.func28.func35.func37"
   282  			ppanic("r != 2350")
   283  		}
   284  		if a != 2000 {
   285  			ppanic("a != 2000")
   286  		}
   287  	}
   288  }
   289  
   290  //go:noinline
   291  func ppanic(s string) { // ERROR "leaking param: s"
   292  	panic(s) // ERROR "s escapes to heap"
   293  }
   294  

View as plain text