base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent)
}
+ assignTemp := func(n ir.Node, init *ir.Nodes) {
+ // Preserve any side effects of n by assigning it to an otherwise unused temp.
+ pos := n.Pos()
+ tmp := typecheck.TempAt(pos, fn, n.Type())
+ init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
+ init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, tmp, n)))
+ }
+
switch n.Op() {
case ir.OMAKESLICE:
// Check if we can replace a non-constant argument to make with
r = &n.Len
}
- if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL {
- lit, ok := s.(*ir.BasicLit)
- if !ok || lit.Val().Kind() != constant.Int {
- base.Fatalf("unexpected BasicLit Kind")
- }
- if constant.Compare(lit.Val(), token.GEQ, constant.MakeInt64(0)) {
- *r = lit
+ if (*r).Op() != ir.OLITERAL {
+ if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL {
+ lit, ok := s.(*ir.BasicLit)
+ if !ok || lit.Val().Kind() != constant.Int {
+ base.Fatalf("unexpected BasicLit Kind")
+ }
+ if constant.Compare(lit.Val(), token.GEQ, constant.MakeInt64(0)) {
+ // Preserve any side effects of the original expression, then replace it.
+ assignTemp(*r, n.PtrInit())
+ *r = lit
+ }
}
}
case ir.OCONVIFACE:
if base.Debug.EscapeDebug >= 3 {
base.WarnfAt(n.Pos(), "rewriting OCONVIFACE value from %v (%v) to %v (%v)", conv.X, conv.X.Type(), v, v.Type())
}
+ // Preserve any side effects of the original expression, then replace it.
+ assignTemp(conv.X, conv.PtrInit())
v := v.(*ir.BasicLit)
conv.X = ir.NewBasicLit(conv.X.Pos(), conv.X.Type(), v.Val())
typecheck.Expr(conv)
--- /dev/null
+// run
+
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+)
+
+func crashOnErr(err error) bool {
+ if err != nil {
+ panic(err)
+ }
+ return false
+}
+
+func main() {
+ defer func() {
+ if recover() == nil {
+ fmt.Println("failed to have expected panic")
+ os.Exit(1)
+ }
+ }()
+ fmt.Println(crashOnErr(errors.New("test error")))
+}
--- /dev/null
+// run
+
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+)
+
+func crashOnErr(err error) int {
+ if err != nil {
+ panic(err)
+ }
+ return 10
+}
+
+func main() {
+ defer func() {
+ if recover() == nil {
+ fmt.Println("failed to have expected panic")
+ os.Exit(1)
+ }
+ }()
+
+ s := make([]int, crashOnErr(errors.New("test error")))
+ println("unreachable: len(s) =", len(s))
+}
--- /dev/null
+// run
+
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+)
+
+type S struct{ a, b int }
+
+func crashOnErr1(err error) S {
+ if err != nil {
+ panic(err)
+ }
+ return S{} // zero value struct
+}
+
+func f1() {
+ defer func() {
+ if recover() == nil {
+ fmt.Println("failed to have expected panic")
+ os.Exit(1)
+ }
+ }()
+ fmt.Println(crashOnErr1(errors.New("test error")))
+}
+
+func crashOnErr2(err error) S {
+ if err != nil {
+ panic(err)
+ }
+ return S{1, 2} // not zero value struct
+}
+
+func f2() {
+ defer func() {
+ if recover() == nil {
+ fmt.Println("failed to have expected panic")
+ os.Exit(1)
+ }
+ }()
+ fmt.Println(crashOnErr2(errors.New("test error")))
+}
+
+func main() {
+ f1()
+ f2()
+}