Files
tinygo/testdata/recover.go
T
Ayke van Laethem 88d273da97 compiler, runtime: implement recoverable divide-by-zero panic
This gets the math/bits and go/constant package tests to pass.

Unfortunately, this also has a binary size impact of around 150-200
bytes in many cases. I'm a bit on the edge on whether this is worth it,
since it's mostly used for getting package tests to work. But at the
same time, having working package tests is very valuable.
2025-02-26 12:56:19 +01:00

151 lines
2.3 KiB
Go

package main
import (
"runtime"
"sync"
)
var wg sync.WaitGroup
func main() {
println("# simple recover")
recoverSimple()
println("\n# recover with result")
result := recoverWithResult()
println("result:", result)
println("\n# nested defer frame")
nestedDefer()
println("\n# nested panic: panic inside recover")
nestedPanic()
println("\n# panic inside defer")
panicInsideDefer()
println("\n# panic replace")
panicReplace()
println("\n# defer panic")
deferPanic()
println("\n# runtime panics")
runtimePanicDivByZero(1, 0)
println("\n# runtime.Goexit")
runtimeGoexit()
}
func recoverSimple() {
defer func() {
println("recovering...")
printitf("recovered:", recover())
}()
println("running panic...")
panic("panic")
}
func recoverWithResult() (result int) {
defer func() {
printitf("recovered:", recover())
}()
result = 3
println("running panic...")
panic("panic")
}
func nestedDefer() {
defer func() {
printitf("recovered:", recover())
}()
func() {
// The defer here doesn't catch the panic using recover(), so the outer
// panic should do that.
defer func() {
println("deferred nested function")
}()
panic("panic")
}()
println("unreachable")
}
func nestedPanic() {
defer func() {
printitf("recovered 1:", recover())
defer func() {
printitf("recovered 2:", recover())
}()
panic("foo")
}()
panic("panic")
}
func panicInsideDefer() {
defer func() {
printitf("recovered:", recover())
}()
defer func() {
panic("panic")
}()
}
func panicReplace() {
defer func() {
printitf("recovered:", recover())
}()
defer func() {
println("panic 2")
panic("panic 2")
}()
println("panic 1")
panic("panic 1")
}
func deferPanic() {
defer func() {
printitf("recovered from deferred call:", recover())
}()
// This recover should not do anything.
defer recover()
defer panic("deferred panic")
println("defer panic")
}
func runtimePanicDivByZero(a, b int) int {
defer func() {
if err := recover(); err != nil {
println("recovered:", err)
}
}()
return a / b
}
func runtimeGoexit() {
wg.Add(1)
go func() {
defer func() {
println("Goexit deferred function, recover is nil:", recover() == nil)
wg.Done()
}()
runtime.Goexit()
}()
wg.Wait()
}
func printitf(msg string, itf interface{}) {
switch itf := itf.(type) {
case string:
println(msg, itf)
default:
println(msg, itf)
}
}