diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index e03866aad..630d95d74 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -522,6 +522,19 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl, pkg *types. } } + // Emit defaults for named returns. + if decl.Type.Results.NumFields() != 0 { + for _, arg := range decl.Type.Results.List { + for _, id := range arg.Names { + if id.Name != "_" { + i := c.scope.newLocal(id.Name) + c.emitDefault(c.typeOf(arg.Type)) + c.emitStoreByIndex(varLocal, i) + } + } + } + } + ast.Walk(c, decl.Body) // If we have reached the end of the function without encountering `return` statement, @@ -763,7 +776,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { for i := len(results.List) - 1; i >= 0; i-- { names := results.List[i].Names for j := len(names) - 1; j >= 0; j-- { - c.emitLoadVar("", names[j].Name) + if names[j].Name == "_" { + c.emitDefault(c.typeOf(results.List[i].Type)) + } else { + c.emitLoadVar("", names[j].Name) + } } } } diff --git a/pkg/compiler/return_test.go b/pkg/compiler/return_test.go index 437f7cd9b..c9cf60e83 100644 --- a/pkg/compiler/return_test.go +++ b/pkg/compiler/return_test.go @@ -120,6 +120,19 @@ func TestNamedReturn(t *testing.T) { t.Run("AnotherVariable", runCase("b, c", big.NewInt(5))) } +func TestNamedReturnDefault(t *testing.T) { + src := `package foo + func Main() int { + a, b, c := f() + return a + b + c + } + func f() (_ int, b int, c int) { + b += 1 + return + }` + eval(t, src, big.NewInt(1)) +} + func TestTypeAssertReturn(t *testing.T) { src := ` package main