Skip to content

goghcrow/go-try

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

33 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐–๐ก๐š๐ญ ๐ข๐ฌ ๐•˜๐• -๐•ฅ๐•ฃ๐•ช

A source to source translator for error-propagating in golang.

The implementation of Proposal: A built-in Go error check function, try.

Quick Start

Create source files ending with _try.go / _try_test.go.

Build tag //go:build try required.

Then go generate -tags try ./... (or run by IDE whatever).

And it is a good idea to switch custom build tag to try when working in goland or vscode, so IDE will be happy to index and check your code.

Example

Create file copyfile_try.go.

//go:build try

//go:generate go install github.com/goghcrow/go-try/cmd/trygen@main
//go:generate trygen

package example

import (
	"fmt"
	"io"
	"os"

	. "github.com/goghcrow/go-try"
)

// CopyFile example
// from https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md#examples
//
//goland:noinspection GoUnhandledErrorResult
func CopyFile(src, dst string) (err error) {
	defer HandleErrorf(&err, "copy %s %s", src, dst)

	r := Try(os.Open(src))
	defer r.Close()

	w := Try(os.Create(dst))
	defer func() {
		w.Close()
		if err != nil {
			os.Remove(dst) // only if a โ€œtryโ€ fails
		}
	}()

	Try(io.Copy(w, r))
	Try0(w.Close())
	return nil
}

func HandleErrorf(err *error, format string, args ...any) {
	if *err != nil {
		*err = fmt.Errorf(format+": %v", append(args, *err)...)
	}
}

run go:generate and output copyfile.go.

//go:build !try

// Code generated by github.com/goghcrow/go-try DO NOT EDIT.
package example

import (
	"fmt"
	"io"
	"os"
)

func CopyFile(src, dst string) (err error) {
	defer HandleErrorf(&err, "copy %s %s", src, dst)
	๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := os.Open(src)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		return
	}
	r := ๐˜ƒ๐—ฎ๐—น๐Ÿญ
	defer r.Close()
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := os.Create(dst)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
		return
	}
	w := ๐˜ƒ๐—ฎ๐—น๐Ÿฎ
	defer func() {
		w.Close()
		if err != nil {
			os.Remove(dst)
		}
	}()
	_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := io.Copy(w, r)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
		err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
		return
	}

	๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ := w.Close()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ != nil {
		err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ
		return
	}

	return nil
}
func HandleErrorf(err *error, format string, args ...any) {
	if *err != nil {
		*err = fmt.Errorf(format+": %v", append(args, *err)...)
	}
}

Translating Examples

prelude

package test

func func1[A, R any](a A) (_ R, _ error) { return }

func return1[A any]() (_ A)                          { return }
func ret0Err() (_ error)                             { return }
func ret1Err[A any]() (_ A, _ error)                 { return }
func ret2Err[A, B any]() (_ A, _ B, _ error)         { return }
func ret3Err[A, B, C any]() (_ A, _ B, _ C, _ error) { return }

func consume1[A any](A)             {}
func consume2[A, B any](A, B)       {}
func consume3[A, B, C any](A, B, C) {}

func id[A any](a A) A { return a }

func handleErrorf(err *error, format string, args ...interface{}) {
	if *err != nil {
		*err = fmt.Errorf(format+": %v", append(args, *err)...)
	}
}

Error Handling

Before

After

func error_wrapping() (a int, err error) {
	defer handleErrorf(&err, "something wrong")
	Try(ret1Err[bool]())
	a = 42
	return
}
func error_wrapping() (a int, err error) {
    defer handleErrorf(&err, "something wrong")
    _, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[bool]()
    if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
        err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
        return
    }
    a = 42
    return
}

Order of Evaluation

Before

After

type (
	A = int
	B = int
	C = int
)
println(
	[]func(int) int{}[id[int](0)+Try(ret1Err[A]())](
		id[int](1)+Try(ret1Err[B]()),
	) + Try(ret1Err[C]()) + id[int](2),
)
๐˜ƒ๐—ฎ๐—น๐Ÿญ := id[int](0)
๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[A]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
}
๐˜ƒ๐—ฎ๐—น๐Ÿฏ := []func(int) int{}[๐˜ƒ๐—ฎ๐—น๐Ÿญ+๐˜ƒ๐—ฎ๐—น๐Ÿฎ]
๐˜ƒ๐—ฎ๐—น๐Ÿฐ := id[int](1)
๐˜ƒ๐—ฎ๐—น๐Ÿฑ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[B]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
}
๐˜ƒ๐—ฎ๐—น๐Ÿฒ := ๐˜ƒ๐—ฎ๐—น๐Ÿฏ(๐˜ƒ๐—ฎ๐—น๐Ÿฐ + ๐˜ƒ๐—ฎ๐—น๐Ÿฑ)
๐˜ƒ๐—ฎ๐—น๐Ÿณ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ret1Err[C]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
}
๐˜ƒ๐—ฎ๐—น๐Ÿด := id[int](2)
println(๐˜ƒ๐—ฎ๐—น๐Ÿฒ + ๐˜ƒ๐—ฎ๐—น๐Ÿณ + ๐˜ƒ๐—ฎ๐—น๐Ÿด)

Logical Operator Or

Before

After

_ = id(true) || Try(func1[int, bool](2)) || id(false)
๐˜ƒ๐—ฎ๐—น๐Ÿญ := id(true)
if !๐˜ƒ๐—ฎ๐—น๐Ÿญ {
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[int, bool](2)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
	}
	๐˜ƒ๐—ฎ๐—น๐Ÿญ = ๐˜ƒ๐—ฎ๐—น๐Ÿฎ
}
if !๐˜ƒ๐—ฎ๐—น๐Ÿญ {
	๐˜ƒ๐—ฎ๐—น๐Ÿญ = id(false)
}
_ = ๐˜ƒ๐—ฎ๐—น๐Ÿญ

Logical Operator And

Before

After

_ = id(true) && Try(func1[int, bool](2)) && id(false)
๐˜ƒ๐—ฎ๐—น๐Ÿญ := id(true)
if ๐˜ƒ๐—ฎ๐—น๐Ÿญ {
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[int, bool](2)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
	}
	๐˜ƒ๐—ฎ๐—น๐Ÿญ = ๐˜ƒ๐—ฎ๐—น๐Ÿฎ
}
if ๐˜ƒ๐—ฎ๐—น๐Ÿญ {
	๐˜ƒ๐—ฎ๐—น๐Ÿญ = id(false)
}
_ = ๐˜ƒ๐—ฎ๐—น๐Ÿญ

If Stmt

Before

After

if Try(func1[int, bool](1)) {
} else if false {
} else if a := Try(func1[int, bool](2)); a {
} else if Try(func1[int, bool](3)) {
} else if true {
}
๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[int, bool](1)
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
}
if ๐˜ƒ๐—ฎ๐—น๐Ÿญ {
} else if false {
} else {
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := func1[int, bool](2)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
	}
	if a := ๐˜ƒ๐—ฎ๐—น๐Ÿฎ; a {
	} else {
		๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := func1[int, bool](3)
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
		}
		if ๐˜ƒ๐—ฎ๐—น๐Ÿฏ {
		} else if true {
		}
	}
}

For Stmt

Before

After

for i := Try(ret1Err[A]()); 
    Try(func1[int, bool](i)); Try(func1[A, C](i)) {
    println(i)
}
๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[A]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
	err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
	return
}
for i := ๐˜ƒ๐—ฎ๐—น๐Ÿญ; ; {
	๐—ฝ๐—ผ๐˜€๐˜๐Ÿญ := func() (_ E๐—ฟ๐—ฟ๐—ผ๐—ฟ) {
		_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[A, C](i)
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		}
		return
	}
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := func1[int, bool](i)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
	}
	if !๐˜ƒ๐—ฎ๐—น๐Ÿฎ {
		break
	}
	println(i)
	๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ๐—ฝ๐—ผ๐˜€๐˜๐Ÿญ()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
	}
}

Range Stmt

Before

After

Outer:
	for range Try(ret1Err[[]int]()) {
	Inner:
		for range Try(ret1Err[[]string]()) {
			switch a {
			case 1:
				goto Inner
			case 2:
				goto Outer
			case 3:
				break Inner
			case 4:
				break Outer
			case 5:
				continue Inner
			case 6:
				continue Outer
			}
		}
	}
๐—Ÿ_๐—š๐—ผ๐˜๐—ผ_๐—ข๐˜‚๐˜๐—ฒ๐—ฟ๐Ÿญ:
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[[]int]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		}
	Outer:
		for range ๐˜ƒ๐—ฎ๐—น๐Ÿญ {
		๐—Ÿ_๐—š๐—ผ๐˜๐—ผ_๐—œ๐—ป๐—ป๐—ฒ๐—ฟ๐Ÿญ:
			{
				๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[[]string]()
				if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
					return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
				}
			Inner:
				for range ๐˜ƒ๐—ฎ๐—น๐Ÿฎ {
					switch a {
					case 1:
						goto ๐—Ÿ_๐—š๐—ผ๐˜๐—ผ_๐—œ๐—ป๐—ป๐—ฒ๐—ฟ๐Ÿญ
					case 2:
						goto ๐—Ÿ_๐—š๐—ผ๐˜๐—ผ_๐—ข๐˜‚๐˜๐—ฒ๐—ฟ๐Ÿญ
					case 3:
						break Inner
					case 4:
						break Outer
					case 5:
						continue Inner
					case 6:
						continue Outer
					}
				}
			}
		}
	}

Switch Stmt

Before

After

switch i := Try(func1[int, A](0)); Try(func1[int, A](i)) {
    case Try(func1[int, B](i)):
        println("B")
    case id[int](i):
        println("C")
    case Try(func1[int, D](i)):
        println("D1")
    case id[int](i):
        println("E")
    case Try(func1[int, D](i)):
        println("D2")
    default:
        println("default")
}
{
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[int, A](0)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
	}
	i := ๐˜ƒ๐—ฎ๐—น๐Ÿฎ
	๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := func1[int, A](i)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
	}
	๐˜ƒ๐—ฎ๐—น๐Ÿญ := ๐˜ƒ๐—ฎ๐—น๐Ÿฏ
	๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := func1[int, B](i)
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
	}
	if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฐ {
		println("B")
	} else if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == id[int](i) {
		println("C")
	} else {
		๐˜ƒ๐—ฎ๐—น๐Ÿฑ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ := func1[int, D](i)
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ
		}
		if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฑ {
			println("D1")
		} else if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == id[int](i) {
			println("E")
		} else {
			๐˜ƒ๐—ฎ๐—น๐Ÿฒ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ := func1[int, D](i)
			if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ != nil {
				return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ
			}
			if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฒ {
				println("D2")
			} else {
				println("default")
			}
		}
	}
}

Switch Stmt

Before

After

outer:
	switch {
	case Try(func1[int, A](1)) == 42:
		println("outer")
	inner:
		switch {
		case Try(func1[int, B](1)) == 42:
			break inner
		case Try(func1[int, C](1)) == 42:
			goto inner
		case Try(func1[int, D](1)) == 42:
			println("inner")
			break outer
		case Try(func1[int, E](1)) == 42:
			println("inner")
			goto outer
		}
	default:
		println("default")
	}
outer:
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := func1[int, A](1)
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		}
		if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == 42 {
			println("outer")
		inner:
			{
				๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := func1[int, B](1)
				if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
					return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
				}
				if ๐˜ƒ๐—ฎ๐—น๐Ÿฎ == 42 {
					goto ๐—Ÿ_๐—•๐—ฟ๐—ธ๐—ง๐—ผ_๐—ถ๐—ป๐—ป๐—ฒ๐—ฟ๐Ÿญ
				} else {
					๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := func1[int, C](1)
					if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
						return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
					}
					if ๐˜ƒ๐—ฎ๐—น๐Ÿฏ == 42 {
						goto inner
					} else {
						๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ := func1[int, D](1)
						if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ != nil {
							return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ
						}
						if ๐˜ƒ๐—ฎ๐—น๐Ÿฐ == 42 {
							println("inner")
							goto ๐—Ÿ_๐—•๐—ฟ๐—ธ๐—ง๐—ผ_๐—ผ๐˜‚๐˜๐—ฒ๐—ฟ๐Ÿญ
						} else {
							๐˜ƒ๐—ฎ๐—น๐Ÿฑ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ := func1[int, E](1)
							if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ != nil {
								return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ
							}
							if ๐˜ƒ๐—ฎ๐—น๐Ÿฑ == 42 {
								println("inner")
								goto outer
							}
						}
					}
				}
			๐—Ÿ_๐—•๐—ฟ๐—ธ๐—ง๐—ผ_๐—ถ๐—ป๐—ป๐—ฒ๐—ฟ๐Ÿญ:
			}
		} else {
			println("default")
		}
	๐—Ÿ_๐—•๐—ฟ๐—ธ๐—ง๐—ผ_๐—ผ๐˜‚๐˜๐—ฒ๐—ฟ๐Ÿญ:
	}

Switch Stmt

Before

After

type (
	A = int
	B = int
	C = int
	D = int
	E = int
	F = int
)
switch i {
case Try(ret1Err[A]()):
	Try(ret1Err[B]())
	fallthrough
case Try(ret1Err[C]()):
	Try(ret1Err[D]())
	fallthrough
case Try(ret1Err[E]()):
	Try(ret1Err[F]())
}
type (
	A = int
	B = int
	C = int
	D = int
	E = int
	F = int
)
{
	๐˜ƒ๐—ฎ๐—น๐Ÿญ := i
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[A]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		return
	}
	if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฎ {
		{
			_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[B]()
			if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
				err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
				return
			}

		}
		{
			_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ret1Err[D]()
			if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
				err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
				return
			}

		}
		{
			_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ := ret1Err[F]()
			if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ != nil {
				err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ
				return
			}

		}
	} else {
		๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ := ret1Err[C]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ != nil {
			err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ
			return
		}
		if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฏ {
			{
				_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ := ret1Err[D]()
				if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ != nil {
					err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ
					return
				}

			}
			{
				_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ := ret1Err[F]()
				if ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ != nil {
					err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ
					return
				}

			}
		} else {
			๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿด := ret1Err[E]()
			if ๐—ฒ๐—ฟ๐—ฟ๐Ÿด != nil {
				err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿด
				return
			}
			if ๐˜ƒ๐—ฎ๐—น๐Ÿญ == ๐˜ƒ๐—ฎ๐—น๐Ÿฐ {
				_, ๐—ฒ๐—ฟ๐—ฟ๐Ÿต := ret1Err[F]()
				if ๐—ฒ๐—ฟ๐—ฟ๐Ÿต != nil {
					err = ๐—ฒ๐—ฟ๐—ฟ๐Ÿต
					return
				}

			}
		}
	}
}

Select Stmt

Before

After

type (
	A = int
	B = int
	C = int
	D = int
	E = int
	F = int
	G = int
	H = int
)
select {
    case <-Try(ret1Err[chan A]()):
    case *Try(ret1Err[*B]()), *Try(ret1Err[*bool]()) = 
        <-Try(ret1Err[chan C]()):
    case Try(ret1Err[chan D]()) 
        <- Try(ret1Err[E]()):
    case Try(ret1Err[[]F]())[Try(ret1Err[G]())] = 
        <-Try(ret1Err[chan H]()):
    default:
}
type (
	A = int
	B = int
	C = int
	D = int
	E = int
	F = int
	G = int
	H = int
)
๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[chan A]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
}
๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[chan C]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
}
๐˜ƒ๐—ฎ๐—น๐Ÿฒ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ := ret1Err[chan D]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฑ
}
๐˜ƒ๐—ฎ๐—น๐Ÿณ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ := ret1Err[E]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฒ
}
๐˜ƒ๐—ฎ๐—น๐Ÿด, ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ := ret1Err[chan H]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ != nil {
	return ๐—ฒ๐—ฟ๐—ฟ๐Ÿณ
}
select {
    case <-๐˜ƒ๐—ฎ๐—น๐Ÿญ:
    case ๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ผ๐—ธ๐Ÿญ := <-๐˜ƒ๐—ฎ๐—น๐Ÿฎ:
        ๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ret1Err[*B]()
        if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
            return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
        }
        *๐˜ƒ๐—ฎ๐—น๐Ÿฏ = ๐˜ƒ๐—ฎ๐—น๐Ÿฐ
        ๐˜ƒ๐—ฎ๐—น๐Ÿฑ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ := ret1Err[*bool]()
        if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ != nil {
            return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฐ
        }
        *๐˜ƒ๐—ฎ๐—น๐Ÿฑ = ๐—ผ๐—ธ๐Ÿญ
    case ๐˜ƒ๐—ฎ๐—น๐Ÿฒ <- ๐˜ƒ๐—ฎ๐—น๐Ÿณ:
    case ๐˜ƒ๐—ฎ๐—น๐Ÿญ๐Ÿญ := <-๐˜ƒ๐—ฎ๐—น๐Ÿด:
        ๐˜ƒ๐—ฎ๐—น๐Ÿต, ๐—ฒ๐—ฟ๐—ฟ๐Ÿด := ret1Err[[]F]()
        if ๐—ฒ๐—ฟ๐—ฟ๐Ÿด != nil {
            return ๐—ฒ๐—ฟ๐—ฟ๐Ÿด
        }
        ๐˜ƒ๐—ฎ๐—น๐Ÿญ๐Ÿฌ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿต := ret1Err[G]()
        if ๐—ฒ๐—ฟ๐—ฟ๐Ÿต != nil {
            return ๐—ฒ๐—ฟ๐—ฟ๐Ÿต
        }
        ๐˜ƒ๐—ฎ๐—น๐Ÿต[๐˜ƒ๐—ฎ๐—น๐Ÿญ๐Ÿฌ] = ๐˜ƒ๐—ฎ๐—น๐Ÿญ๐Ÿญ
    default:
}

Goto Stmt

Before

After

L:
    var a = Try(ret1Err[int]())
    goto L
    println(a)
L:
    ๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[int]()
    if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
        return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
    }
    var a = ๐˜ƒ๐—ฎ๐—น๐Ÿญ
    goto L
    println(a)

Assign Stmt

Before

After

*id(&i) = Try(ret1Err[int]())
๐˜ƒ๐—ฎ๐—น๐Ÿญ := id(&i)
๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[int]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
	return
}
*๐˜ƒ๐—ฎ๐—น๐Ÿญ = ๐˜ƒ๐—ฎ๐—น๐Ÿฎ

Map Index Expr

Before

After

// panic when writting nil map
{
	var m map[int]int
	m[Try(ret1Err[int]())] = 1
}

// won't panic when reading nil map
{
	var m map[int]int
	println(m[0], Try(ret1Err[int]()))
}

// panic when reading map[any]T
{
	var m map[any]int
	println(m[0], Try(ret1Err[int]()))
}
{
	var m map[int]int
	๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[int]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
	}
	m[๐˜ƒ๐—ฎ๐—น๐Ÿญ] = 1
}
{
	var m map[int]int
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[int]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
	}
	println(m[0], ๐˜ƒ๐—ฎ๐—น๐Ÿฎ)
}
{
	var m map[any]int
	๐˜ƒ๐—ฎ๐—น๐Ÿฏ := m[0]
	๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ret1Err[int]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
		return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
	}
	println(๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐˜ƒ๐—ฎ๐—น๐Ÿฐ)
}

Type Assert

Before

After

expr, ok := Try(ret1Err[ast.Node]()).(ast.Expr)
_, _ = expr, ok
๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[ast.Node]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
    return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
}
expr, ok := ๐˜ƒ๐—ฎ๐—น๐Ÿญ.(ast.Expr)
_, _ = expr, ok

Tuple Assign

Before

After

_, _ = map[int]int{}[Try(ret1Err[int]())]
๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[int]()
if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
    return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
}
_, _ = map[int]int{}[๐˜ƒ๐—ฎ๐—น๐Ÿญ]

Selector Expr

Before

After

func rewrite_ptr_selector_expr() error {
	var x *ast.CallExpr
	{
		// MAY PANIC
		consume2(x.Args, Try(ret1Err[string]()))
	}
	{
		// MUST NOT PANIC
		consume2(x.Pos, Try(ret1Err[string]()))
	}
	{
		// MAY PANIC
		consume2(x.Pos(), Try(ret1Err[string]()))
	}
	return nil
}

func rewrite_iface_selector_expr() error {
	var x ast.Node
	{
        // MAY PANIC
        consume2(x.Pos, Try(ret1Err[string]()))
	}
	{
        // MAY PANIC
        consume2(x.Pos(), Try(ret1Err[string]()))
	}
	return nil
}
func rewrite_ptr_selector_expr() error {
	var x *ast.CallExpr
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿญ := x.Args
		๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[string]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		}
		consume2(๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐˜ƒ๐—ฎ๐—น๐Ÿฎ)
	}
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[string]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
		}
		consume2(x.Pos, ๐˜ƒ๐—ฎ๐—น๐Ÿฏ)
	}
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿฐ := x.Pos()
		๐˜ƒ๐—ฎ๐—น๐Ÿฑ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ := ret1Err[string]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฏ
		}
		consume2(๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐˜ƒ๐—ฎ๐—น๐Ÿฑ)
	}
	return nil
}
func rewrite_iface_selector_expr() error {
	var x ast.Node
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿญ := x.Pos
		๐˜ƒ๐—ฎ๐—น๐Ÿฎ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[string]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ
		}
		consume2(๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐˜ƒ๐—ฎ๐—น๐Ÿฎ)
	}
	{
		๐˜ƒ๐—ฎ๐—น๐Ÿฏ := x.Pos()
		๐˜ƒ๐—ฎ๐—น๐Ÿฐ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[string]()
		if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
			return ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ
		}
		consume2(๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐˜ƒ๐—ฎ๐—น๐Ÿฐ)
	}
	return nil
}

Runtime Panic

Before

After

type X struct{ x int }
{
	var x X
	_ = x.x + Try(ret1Err[int]())
}
{
	var x *X
	_ = x.x + Try(ret1Err[int]())
}
type X struct{ x int }
{
	var x X
	๐˜ƒ๐—ฎ๐—น๐Ÿญ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ := ret1Err[int]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿญ != nil {
		return
	}
	_ = x.x + ๐˜ƒ๐—ฎ๐—น๐Ÿญ
}
{
	var x *X
	๐˜ƒ๐—ฎ๐—น๐Ÿฎ := x.x
	๐˜ƒ๐—ฎ๐—น๐Ÿฏ, ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ := ret1Err[int]()
	if ๐—ฒ๐—ฟ๐—ฟ๐Ÿฎ != nil {
		return
	}
	_ = ๐˜ƒ๐—ฎ๐—น๐Ÿฎ + ๐˜ƒ๐—ฎ๐—น๐Ÿฏ
}

runtime_panic_try_test.go

runtime_panic_test.go

About

The implementation of Proposal: A built-in Go error check function, try.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published