Categorygithub.com/goghcrow/go-try
modulepackage
0.0.0-20240331123324-11dab801cbfc
Repository: https://github.com/goghcrow/go-try.git
Documentation: pkg.go.dev

# README

𝐖𝐡𝐚𝐭 𝐢𝐬 𝕘𝕠-𝕥𝕣𝕪

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

# Packages

No description provided by the author
Code generated by github.com/goghcrow/go-try DO NOT EDIT.
No description provided by the author
No description provided by the author

# Functions

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author