diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index 60935cbbe..fb118cffd 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -313,3 +313,14 @@ func TestJumpOptimize(t *testing.T) { require.Equal(t, b[mi.Range.End], byte(opcode.RET)) } } + +func TestFunctionUnusedParameters(t *testing.T) { + src := `package foo + func add13(a int, _ int, _1 int, _ int) int { + return a + _1 + } + func Main() int { + return add13(1, 10, 100, 1000) + }` + eval(t, src, big.NewInt(101)) +} diff --git a/pkg/compiler/vars.go b/pkg/compiler/vars.go index a12aa1459..b0b92496c 100644 --- a/pkg/compiler/vars.go +++ b/pkg/compiler/vars.go @@ -2,6 +2,7 @@ package compiler import ( "go/ast" + "strconv" ) type varScope struct { @@ -70,6 +71,12 @@ func (c *varScope) newVariable(t varType, name string) int { case varLocal: return c.newLocal(name) case varArgument: + if name == "_" { + // See #2204. This name won't actually be referenced. + // This approach simplifies argument allocation and + // makes debugging easier. + name = "%_" + strconv.FormatUint(uint64(len(c.arguments)), 10) + } _, ok := c.arguments[name] if ok { panic("argument is already allocated")