Files
go/test/escape4.go
Ilya Torbin 0977a589b4 cmd/compile: allow inlining of functions that call recover
Since CL 685355, gorecover detects a valid recover call by unwinding
the stack and counting the non-wrapper frames between gopanic and
gorecover. The unwinder counts inline-expanded frames as separate
logical frames, so inlining a function that calls recover no longer
changes whether that recover stops the panic. Drop the restriction
and charge the usual call cost for recover.

This allows inlining of ordinary calls to functions that call
recover, including calls from compiler-generated wrappers such as
deferred method values, where the inlined recover remains active.
Deferred call sites are still not inline-expanded, so deferred
recover closures like the ones in net/http.(*conn).serve and
text/template.safeCall are only marked inlinable; that becomes
useful if the inliner later learns to expand deferred calls.

In test/closure3.dir/main.go and test/codegen/issue60324.go, recover
was used as a device to keep a closure from being inlined; use defer
instead, which still disables inlining. Update test/escape4.go, which
expected functions calling recover to not be inlinable. Add
test/recover6.go to verify that recover semantics are unchanged when
functions calling recover are inlined.

Change-Id: I4e15622af62d05faefc2a482b43fc46e0ac6a52d
Reviewed-on: https://go-review.googlesource.com/c/go/+/815361
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
2026-08-31 12:30:31 -07:00

60 lines
1.4 KiB
Go

// errorcheck -0 -m
//go:build !goexperiment.newinliner
// Copyright 2010 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.
// Test, using compiler diagnostic flags, that the escape analysis is working.
// Compiles but does not run. Inlining is enabled.
package foo
var p *int
func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x"
return &x
}
var f func()
func f1() {
p = alloc(2) // ERROR "inlining call to alloc" "moved to heap: x"
// Escape analysis used to miss inlined code in closures.
func() { // ERROR "can inline f1.func1"
p = alloc(3) // ERROR "inlining call to alloc" "moved to heap: x"
}() // ERROR "inlining call to f1.func1" "inlining call to alloc" "moved to heap: x"
f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2"
p = alloc(3) // ERROR "inlining call to alloc" "moved to heap: x"
}
f()
}
func f2() {} // ERROR "can inline f2"
// Both panic and recover are allowed to inline.
func f3() { panic(1) } // ERROR "can inline f3" "1 escapes to heap"
func f4() { recover() } // ERROR "can inline f4"
func f5() *byte { // ERROR "can inline f5"
type T struct {
x [1]byte
}
t := new(T) // ERROR "new.T. escapes to heap"
return &t.x[0]
}
func f6() *byte { // ERROR "can inline f6"
type T struct {
x struct {
y byte
}
}
t := new(T) // ERROR "new.T. escapes to heap"
return &t.x.y
}