From 377646589d5fb0224014683e0d1f1db35e60c3ac Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Fri, 24 May 2024 17:56:31 -0400 Subject: [PATCH] text/template: clarify error when too few or too many return values Prior to CL 561115, calling a function without any return values would print "function called with 0 args; should be 1 or 2". Afterwards, the error message became "too many return values". Keep the improvement of referring to return values rather than args, and bring back clarity about their actual and permitted numbers. Change-Id: I2c014e4633208cc7052fac265a995a8f2fe68151 Reviewed-on: https://go-review.googlesource.com/c/go/+/588355 Reviewed-by: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Auto-Submit: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI --- src/text/template/exec_test.go | 20 ++++++++++++++------ src/text/template/funcs.go | 8 +++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 4ec213d8cfb24d..9903e17d0ef2c8 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -81,7 +81,8 @@ type T struct { NilOKFunc func(*int) bool ErrFunc func() (string, error) PanicFunc func() string - InvalidReturnCountFunc func() (string, error, int) + TooFewReturnCountFunc func() + TooManyReturnCountFunc func() (string, error, int) InvalidReturnTypeFunc func() (string, bool) // Template to test evaluation of templates. Tmpl *Template @@ -170,7 +171,8 @@ var tVal = &T{ NilOKFunc: func(s *int) bool { return s == nil }, ErrFunc: func() (string, error) { return "bla", nil }, PanicFunc: func() string { panic("test panic") }, - InvalidReturnCountFunc: func() (string, error, int) { return "", nil, 0 }, + TooFewReturnCountFunc: func() {}, + TooManyReturnCountFunc: func() (string, error, int) { return "", nil, 0 }, InvalidReturnTypeFunc: func() (string, bool) { return "", false }, Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X } @@ -1746,16 +1748,22 @@ func TestFunctionCheckDuringCall(t *testing.T) { wantErr: "error calling call: wrong number of args for .VariadicFuncInt: got 0 want at least 1", }, { - name: "call invalid return number func", - input: `{{call .InvalidReturnCountFunc}}`, + name: "call too few return number func", + input: `{{call .TooFewReturnCountFunc}}`, data: tVal, - wantErr: "error calling call: too many return values for .InvalidReturnCountFunc", + wantErr: "error calling call: function .TooFewReturnCountFunc has 0 return values; should be 1 or 2", + }, + { + name: "call too many return number func", + input: `{{call .TooManyReturnCountFunc}}`, + data: tVal, + wantErr: "error calling call: function .TooManyReturnCountFunc has 3 return values; should be 1 or 2", }, { name: "call invalid return type func", input: `{{call .InvalidReturnTypeFunc}}`, data: tVal, - wantErr: "error calling call: invalid function signature for .InvalidReturnTypeFunc: second argument should be error; is bool", + wantErr: "error calling call: invalid function signature for .InvalidReturnTypeFunc: second return value should be error; is bool", }, { name: "call pipeline", diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index 6832ae3682deb7..7d63cf8b7bb6db 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -110,18 +110,16 @@ func addFuncs(out, in FuncMap) { // goodFunc reports whether the function or method has the right result signature. func goodFunc(name string, typ reflect.Type) error { - numOut := typ.NumOut() - // We allow functions with 1 result or 2 results where the second is an error. - switch { + switch numOut := typ.NumOut(); { case numOut == 1: return nil case numOut == 2 && typ.Out(1) == errorType: return nil case numOut == 2: - return fmt.Errorf("invalid function signature for %s: second argument should be error; is %s", name, typ.Out(1)) + return fmt.Errorf("invalid function signature for %s: second return value should be error; is %s", name, typ.Out(1)) default: - return fmt.Errorf("too many return values for %s", name) + return fmt.Errorf("function %s has %d return values; should be 1 or 2", name, typ.NumOut()) } }