The Go programming language
  • Go 95.3%
  • Assembly 4.4%
  • C 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Cuong Manh Le dba926f240 cmd/compile, runtime: make recover work in a range-over-func loop body
The body of a range-over-func loop is compiled into a closure that the
iterator calls, so it runs in a frame of its own:

	func foo() {
		for range iter {
			recover()
		}
	}

leaves the stack as

	foo
	runtime.gopanic
	foo
	iter
	foo-range1
	runtime.gorecover

The recover is written directly in foo, so it should recover, but the
runtime decides by the frame the call was made in, and that frame is the
body's, not foo's.

Whether such a call can recover depends only on the frame the loop is
in, so the runtime can decide that part on entry to the loop, while that
frame is the current one. rangeframe does that and returns the panic the
body may recover, and the body passes it back to gorecoverat, which
recovers it if it is still the one being processed:

	var #recover = runtime.recoverrangefunc()
	iter(func() {
		runtime.gorecoverat(#recover)
	})

This is the same shape as the token deferrangefunc hands out so that a
defer in the body defers to the containing function. A panic is a safe
token to hold onto, unlike the frame it stands for: it does not move
when the stack does, so nothing has to keep it up to date.

Fixes #71685

Change-Id: Iee454fcf757bd91828b9b1fe93076ca32456740e
Reviewed-on: https://go-review.googlesource.com/c/go/+/841045
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: David Chase <drchase@google.com>
2026-09-29 09:19:41 -07:00
.github .github: update PULL_REQUEST_TEMPLATE to match the latest instruction 2026-05-26 15:10:06 -07:00
api go/types: add Scope.Objects iterator and cache Scope.Names 2026-09-21 10:04:38 -07:00
doc spec: string(x) for integers requires x to be of (underlying) type byte or rune 2026-09-24 15:49:11 -07:00
lib lib/time: update to 2026c/2026c 2026-07-09 11:24:04 -07:00
misc all: replace strings.Split with strings.SplitSeq 2025-09-15 17:34:45 -07:00
src cmd/compile, runtime: make recover work in a range-over-func loop body 2026-09-29 09:19:41 -07:00
test cmd/compile, runtime: make recover work in a range-over-func loop body 2026-09-29 09:19:41 -07:00
.gitattributes
.gitignore .gitignore: ignore go test artifacts 2025-11-10 12:41:03 -08:00
codereview.cfg
CONTRIBUTING.md
go.env
LICENSE LICENSE: update per Google Legal 2024-08-09 14:54:31 +00:00
PATENTS
README.md README: fix CC BY license name 2024-07-22 17:45:27 +00:00
SECURITY.md

The Go Programming Language

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Gopher image Gopher image by Renee French, licensed under Creative Commons 4.0 Attribution license.

Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.

Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.

Download and Install

Binary Distributions

Official binary distributions are available at https://go.dev/dl/.

After downloading a binary release, visit https://go.dev/doc/install for installation instructions.

Install From Source

If a binary distribution is not available for your combination of operating system and architecture, visit https://go.dev/doc/install/source for source installation instructions.

Contributing

Go is the work of thousands of contributors. We appreciate your help!

To contribute, please read the contribution guidelines at https://go.dev/doc/contribute.

Note that the Go project uses the issue tracker for bug reports and proposals only. See https://go.dev/wiki/Questions for a list of places to ask questions about the Go language.