github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/ssa/interp/testdata/fixedbugs/issue55086.go (about)

     1  // Copyright 2022 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  package main
     6  
     7  func a() (r string) {
     8  	s := "initial"
     9  	var p *struct{ i int }
    10  	defer func() {
    11  		recover()
    12  		r = s
    13  	}()
    14  
    15  	s, p.i = "set", 2 // s must be set before p.i panics
    16  	return "unreachable"
    17  }
    18  
    19  func b() (r string) {
    20  	s := "initial"
    21  	fn := func() []int { panic("") }
    22  	defer func() {
    23  		recover()
    24  		r = s
    25  	}()
    26  
    27  	s, fn()[0] = "set", 2 // fn() panics before any assignment occurs
    28  	return "unreachable"
    29  }
    30  
    31  func c() (r string) {
    32  	s := "initial"
    33  	var p map[int]int
    34  	defer func() {
    35  		recover()
    36  		r = s
    37  	}()
    38  
    39  	s, p[0] = "set", 2 //s must be set before p[0] index panics"
    40  	return "unreachable"
    41  }
    42  
    43  func d() (r string) {
    44  	s := "initial"
    45  	var p map[int]int
    46  	defer func() {
    47  		recover()
    48  		r = s
    49  	}()
    50  	fn := func() int { panic("") }
    51  
    52  	s, p[0] = "set", fn() // fn() panics before s is set
    53  	return "unreachable"
    54  }
    55  
    56  func e() (r string) {
    57  	s := "initial"
    58  	p := map[int]int{}
    59  	defer func() {
    60  		recover()
    61  		r = s
    62  	}()
    63  	fn := func() int { panic("") }
    64  
    65  	s, p[fn()] = "set", 0 // fn() panics before any assignment occurs
    66  	return "unreachable"
    67  }
    68  
    69  func f() (r string) {
    70  	s := "initial"
    71  	p := []int{}
    72  	defer func() {
    73  		recover()
    74  		r = s
    75  	}()
    76  
    77  	s, p[1] = "set", 0 // p[1] panics after s is set
    78  	return "unreachable"
    79  }
    80  
    81  func g() (r string) {
    82  	s := "initial"
    83  	p := map[any]any{}
    84  	defer func() {
    85  		recover()
    86  		r = s
    87  	}()
    88  	var i any = func() {}
    89  	s, p[i] = "set", 0 // p[i] panics after s is set
    90  	return "unreachable"
    91  }
    92  
    93  func h() (r string) {
    94  	fail := false
    95  	defer func() {
    96  		recover()
    97  		if fail {
    98  			r = "fail"
    99  		} else {
   100  			r = "success"
   101  		}
   102  	}()
   103  
   104  	type T struct{ f int }
   105  	var p *struct{ *T }
   106  
   107  	// The implicit "p.T" operand should be evaluated in phase 1 (and panic),
   108  	// before the "fail = true" assignment in phase 2.
   109  	fail, p.f = true, 0
   110  	return "unreachable"
   111  }
   112  
   113  func main() {
   114  	for _, test := range []struct {
   115  		fn   func() string
   116  		want string
   117  		desc string
   118  	}{
   119  		{a, "set", "s must be set before p.i panics"},
   120  		{b, "initial", "p() panics before s is set"},
   121  		{c, "set", "s must be set before p[0] index panics"},
   122  		{d, "initial", "fn() panics before s is set"},
   123  		{e, "initial", "fn() panics before s is set"},
   124  		{f, "set", "p[1] panics after s is set"},
   125  		{g, "set", "p[i] panics after s is set"},
   126  		{h, "success", "p.T panics before fail is set"},
   127  	} {
   128  		if test.fn() != test.want {
   129  			panic(test.desc)
   130  		}
   131  	}
   132  }